6f7fc4398cb9c73c7a0ed18028db06befa159b63
[jalview.git] / src / jalview / javascript / JSFunctionExec.java
1 package jalview.javascript;\r
2 \r
3 import java.net.URL;\r
4 import java.util.Vector;\r
5 \r
6 import netscape.javascript.JSException;\r
7 import netscape.javascript.JSObject;\r
8 import jalview.bin.JalviewLite;\r
9 \r
10 public class JSFunctionExec implements Runnable\r
11 {\r
12   public JalviewLite jvlite;\r
13 \r
14   public JSFunctionExec(JalviewLite applet)\r
15   {\r
16     jvlite = applet;\r
17     \r
18     jsExecQueue = jvlite.getJsExecQueue();\r
19     jvlite.setExecutor(this);\r
20   }\r
21   public void finalize() {\r
22     jvlite=null;\r
23     executor=null;\r
24     if (jsExecQueue!=null)\r
25     {\r
26       jsExecQueue.clear();\r
27     }\r
28     jsExecQueue=null;\r
29   }\r
30   private Vector jsExecQueue;\r
31 \r
32   private Thread executor = null;\r
33 \r
34   public void stopQueue()\r
35   {\r
36     if (jsExecQueue != null)\r
37     {\r
38       Vector<JSFunctionExec> q=null;\r
39       synchronized (jsExecQueue)\r
40       {\r
41         q = jsExecQueue;\r
42         jsExecQueue = null;\r
43       }\r
44       if (q!=null ) {\r
45         for (JSFunctionExec jx : q)\r
46         {\r
47           jx.jvlite=null;\r
48           \r
49         }\r
50         q.removeAllElements();\r
51         synchronized (q)\r
52         {\r
53           q.notifyAll();\r
54         }\r
55       }\r
56     }\r
57     jvlite=null;\r
58     executor = null;\r
59   }\r
60 \r
61   public void run()\r
62   {\r
63     while (jsExecQueue != null)\r
64     {\r
65       if (jsExecQueue.size() > 0)\r
66       {\r
67         Runnable r = (Runnable) jsExecQueue.elementAt(0);\r
68         jsExecQueue.removeElementAt(0);\r
69         try\r
70         {\r
71           r.run();\r
72         } catch (Exception ex)\r
73         {\r
74           ex.printStackTrace();\r
75         } catch (Error ex)\r
76         {\r
77           ex.printStackTrace();\r
78         }\r
79       }\r
80       else\r
81       {\r
82         try\r
83         {\r
84           synchronized (jsExecQueue)\r
85           {\r
86             jsExecQueue.wait(1000);\r
87           }\r
88         } catch (Exception ex)\r
89         {\r
90         }\r
91         ;\r
92       }\r
93     }\r
94 \r
95   }\r
96 \r
97   /**\r
98    * execute a javascript callback synchronously\r
99    * \r
100    * @param _listener\r
101    * @param objects\r
102    * @throws Exception\r
103    */\r
104   public void executeJavascriptFunction(final String _listener,\r
105           final Object[] objects) throws Exception\r
106   {\r
107     executeJavascriptFunction(false, _listener, objects);\r
108   }\r
109 \r
110   /**\r
111    * execute a javascript callback synchronously or asynchronously\r
112    * \r
113    * @param async\r
114    *          - true to execute asynchronously (do this for gui events)\r
115    * @param _listener\r
116    *          - javascript function\r
117    * @param objects\r
118    *          - arguments\r
119    * @throws Exception\r
120    *           - only if call is synchronous\r
121    */\r
122   public void executeJavascriptFunction(final boolean async,\r
123           final String _listener, Object[] arguments) throws Exception\r
124   {\r
125 \r
126     executeJavascriptFunction(async, _listener, arguments, null);\r
127 \r
128   }\r
129 \r
130   public void executeJavascriptFunction(final boolean async,\r
131           final String _listener, Object[] arguments, final String dbgMsg)\r
132           throws Exception\r
133   {\r
134     final Object[] objects = new Object[arguments != null ? arguments.length\r
135             : 0];\r
136     if (arguments != null)\r
137     {\r
138       System.arraycopy(arguments, 0, objects, 0, arguments.length);\r
139     }\r
140     final Exception[] jsex = new Exception[1];\r
141     Runnable exec = new Runnable()\r
142     {\r
143       public void run()\r
144       {\r
145         try\r
146         {\r
147           JSObject scriptObject = null;\r
148           try\r
149           {\r
150             scriptObject = JSObject.getWindow(jvlite);\r
151           } catch (Exception ex)\r
152           {\r
153           }\r
154           ;\r
155           if (scriptObject != null)\r
156           {\r
157             if (jvlite.debug && dbgMsg != null)\r
158             {\r
159               System.err.println(dbgMsg);\r
160             }\r
161             scriptObject.call(_listener, objects);\r
162           }\r
163         } catch (Exception jex)\r
164         {\r
165           // squash any malformedURLExceptions thrown by windows/safari\r
166           if (!(jex instanceof java.net.MalformedURLException))\r
167           {\r
168             if (jvlite.debug)\r
169             {\r
170               System.err.println(jex);\r
171             }\r
172             if (jex instanceof netscape.javascript.JSException && jvlite.jsfallbackEnabled)\r
173             {\r
174               jsex[0] = (netscape.javascript.JSException) jex;\r
175               if (jvlite.debug)\r
176               {\r
177                 System.err.println("Falling back to javascript: url call");\r
178               }\r
179               StringBuffer sb = new StringBuffer("javascript:" + _listener\r
180                       + "(");\r
181               for (int i = 0; objects != null && i < objects.length; i++)\r
182               {\r
183                 if (i > 0)\r
184                 {\r
185                   sb.append(",");\r
186                 }\r
187                 sb.append("\"");\r
188                 // strip out nulls and complex objects that we can't pass this\r
189                 // way.\r
190                 if (objects[i] != null\r
191                         && !(objects[i].getClass().getName()\r
192                                 .indexOf("jalview") == 0))\r
193                 {\r
194                   sb.append(objects[i].toString());\r
195                 }\r
196                 sb.append("\"");\r
197               }\r
198               sb.append(")");\r
199               if (jvlite.debug)\r
200               {\r
201                 System.err.println(sb.toString());\r
202               }\r
203               // alternate\r
204               URL url = null;\r
205               try\r
206               {\r
207                 url = new URL(sb.toString());\r
208                 jvlite.getAppletContext().showDocument(url);\r
209                 jex = null;\r
210               } catch (Exception uex)\r
211               {\r
212                 jex = uex;\r
213               }\r
214             }\r
215             if (jex != null)\r
216             {\r
217               if (async)\r
218               {\r
219                 jex.printStackTrace();\r
220               }\r
221               else\r
222               {\r
223                 jsex[0] = jex;\r
224               }\r
225             }\r
226             ;\r
227           }\r
228 \r
229         }\r
230       }\r
231     };\r
232     if (async)\r
233     {\r
234       if (executor == null)\r
235       {\r
236         executor = new Thread(new JSFunctionExec(jvlite));\r
237         executor.start();\r
238       }\r
239       synchronized (jsExecQueue)\r
240       {\r
241         jsExecQueue.addElement(exec);\r
242         jsExecQueue.notify();\r
243       }\r
244     }\r
245     else\r
246     {\r
247       // wat for executor to notify us if it's running.\r
248       exec.run();\r
249       if (jsex[0] != null)\r
250       {\r
251         throw (jsex[0]);\r
252       }\r
253     }\r
254   }\r
255 \r
256 }\r