package jalview.javascript; import java.net.URL; import java.util.Vector; import netscape.javascript.JSException; import netscape.javascript.JSObject; import jalview.bin.JalviewLite; public class JSFunctionExec implements Runnable { JalviewLite jvlite; public JSFunctionExec(JalviewLite applet) { jvlite = applet; } private static Vector jsExecQueue; private static Thread executor = null; public static void stopQueue() { if (jsExecQueue != null) { Vector q = jsExecQueue; jsExecQueue = null; q.removeAllElements(); executor.notify(); executor = null; } } public void run() { while (jsExecQueue != null) { if (jsExecQueue.size() > 0) { Runnable r = (Runnable) jsExecQueue.elementAt(0); jsExecQueue.removeElementAt(0); try { r.run(); } catch (Exception ex) { ex.printStackTrace(); } catch (Error ex) { ex.printStackTrace(); } } else { try { synchronized (jsExecQueue) { jsExecQueue.wait(1000); } } catch (Exception ex) { } ; } } } /** * execute a javascript callback asynchronously * * @param _listener * @param objects * @throws Exception */ public void executeJavascriptFunction(final String _listener, final Object[] objects) throws Exception { executeJavascriptFunction(false, _listener, objects); } /** * execute a javascript callback synchronously or asynchronously * * @param async * - true to execute asynchronously (do this for gui events) * @param _listener * - javascript function * @param objects * - arguments * @throws Exception * - only if call is synchronous */ public void executeJavascriptFunction(final boolean async, final String _listener, Object[] arguments) throws Exception { final Object[] objects = new Object[arguments != null ? arguments.length : 0]; if (arguments != null) { System.arraycopy(arguments, 0, objects, 0, arguments.length); } final Exception[] jsex = new Exception[1]; Runnable exec = new Runnable() { public void run() { try { JSObject scriptObject = null; try { scriptObject = JSObject.getWindow(jvlite.applet); } catch (Exception ex) { } ; if (scriptObject != null) { scriptObject.call(_listener, objects); } } catch (Exception jex) { // squash any malformedURLExceptions thrown by windows/safari if (!(jex instanceof java.net.MalformedURLException)) { if (jvlite.debug) { System.err.println(jex); } if (jex instanceof netscape.javascript.JSException) { jsex[0] = (netscape.javascript.JSException) jex; if (jvlite.debug) { System.err.println("Falling back to javascript: url call"); } StringBuffer sb = new StringBuffer("javascript:" + _listener + "("); for (int i = 0; objects != null && i < objects.length; i++) { if (i > 0) { sb.append(","); } sb.append("\""); // strip out nulls and complex objects that we can't pass this // way. if (objects[i] != null && !(objects[i].getClass().getPackage().getName() .indexOf("jalview") == 0)) { sb.append(objects[i].toString()); } sb.append("\""); } sb.append(")"); if (jvlite.debug) { System.err.println(sb.toString()); } // alternate URL url = null; try { url = new URL(sb.toString()); jvlite.getAppletContext().showDocument(url); jex = null; } catch (Exception uex) { jex = uex; } } if (jex != null) { if (async) { jex.printStackTrace(); } else { jsex[0] = new Exception(jex); } } ; } } } }; if (async) { if (JSFunctionExec.executor == null) { JSFunctionExec.jsExecQueue = new Vector(); JSFunctionExec.executor = new Thread(new JSFunctionExec(jvlite)); executor.start(); } synchronized (jsExecQueue) { jsExecQueue.addElement(exec); jsExecQueue.notify(); } } else { exec.run(); if (jsex[0] != null) { throw (jsex[0]); } } } }