/*******************************************************************************
* Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
* Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
*
* This file is part of Jalview.
*
* Jalview is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* Jalview is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Jalview. If not, see .
*******************************************************************************/
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
{
public JalviewLite jvlite;
public JSFunctionExec(JalviewLite applet)
{
jvlite = applet;
jsExecQueue = jvlite.getJsExecQueue();
jvlite.setExecutor(this);
}
public void finalize() {
jvlite=null;
executor=null;
if (jsExecQueue!=null)
{
jsExecQueue.clear();
}
jsExecQueue=null;
}
private Vector jsExecQueue;
private Thread executor = null;
public void stopQueue()
{
if (jsExecQueue != null)
{
Vector q=null;
synchronized (jsExecQueue)
{
q = jsExecQueue;
jsExecQueue = null;
}
if (q!=null ) {
for (JSFunctionExec jx : q)
{
jx.jvlite=null;
}
q.removeAllElements();
synchronized (q)
{
q.notifyAll();
}
}
}
jvlite=null;
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 synchronously
*
* @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
{
executeJavascriptFunction(async, _listener, arguments, null);
}
public void executeJavascriptFunction(final boolean async,
final String _listener, Object[] arguments, final String dbgMsg)
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);
} catch (Exception ex)
{
}
;
if (scriptObject != null)
{
if (jvlite.debug && dbgMsg != null)
{
System.err.println(dbgMsg);
}
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 && jvlite.jsfallbackEnabled)
{
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().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] = jex;
}
}
;
}
}
}
};
if (async)
{
if (executor == null)
{
executor = new Thread(new JSFunctionExec(jvlite));
executor.start();
}
synchronized (jsExecQueue)
{
jsExecQueue.addElement(exec);
jsExecQueue.notify();
}
}
else
{
// wat for executor to notify us if it's running.
exec.run();
if (jsex[0] != null)
{
throw (jsex[0]);
}
}
}
}