KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > openedit > modules > scriptrunner > RhinoScriptRunner


1 /*
2 Copyright (c) 2003 eInnovation Inc. All rights reserved
3
4 This library is free software; you can redistribute it and/or modify it under the terms
5 of the GNU Lesser General Public License as published by the Free Software Foundation;
6 either version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 See the GNU Lesser General Public License for more details.
11 */

12
13 package com.openedit.modules.scriptrunner;
14
15 import org.apache.commons.logging.Log;
16 import org.apache.commons.logging.LogFactory;
17 import org.mozilla.javascript.Context;
18 import org.mozilla.javascript.Function;
19 import org.mozilla.javascript.ImporterTopLevel;
20 import org.mozilla.javascript.NativeArray;
21 import org.mozilla.javascript.NativeJavaObject;
22 import org.mozilla.javascript.Scriptable;
23
24 import com.openedit.OpenEditException;
25
26
27 /**
28  * This implementation of {@link ScriptRunner} uses Mozilla's Rhino JavaScript engine.
29  *
30  * @author Eric Galluzzo
31  */

32 public class RhinoScriptRunner implements ScriptRunner
33 {
34     private static final Log LOGGER = LogFactory.getLog(RhinoScriptRunner.class);
35     protected static Scriptable fieldGlobalScope;
36     protected Script fieldScript;
37     protected Scriptable fieldScope;
38     protected boolean fieldInitialized = false;
39
40     public RhinoScriptRunner()
41     {
42         this(null);
43     }
44
45     /**
46      * ScriptRunner constructor comment.
47      *
48      * @param inScripts DOCUMENT ME!
49      */

50     public RhinoScriptRunner(Script inScripts)
51     {
52         setScript(inScripts);
53
54         //this will associate a runner with the current thread
55
Context context = Context.enter();
56     }
57
58     /**
59      * Returns the globalScope.
60      *
61      * @return Scriptable
62      */

63     public static Scriptable getGlobalScope()
64     {
65         if (fieldGlobalScope == null)
66         {
67             Context context = Context.enter();
68             fieldGlobalScope = new ImporterTopLevel(context);
69             Context.exit();
70         }
71
72         return fieldGlobalScope;
73     }
74
75     /**
76      * Sets the initialized.
77      *
78      * @param initialized The initialized to set
79      */

80     public void setInitialized(boolean initialized)
81     {
82         fieldInitialized = initialized;
83     }
84
85     /**
86      * Returns the initialized.
87      *
88      * @return boolean
89      */

90     public boolean isInitialized()
91     {
92         return fieldInitialized;
93     }
94
95     /**
96      * Sets the scope.
97      *
98      * @param scope The scope to set
99      */

100     public void setScope(Scriptable scope)
101     {
102         fieldScope = scope;
103     }
104
105     /**
106      * Returns the scope.
107      *
108      * @return Scriptable
109      *
110      * @throws ScriptException DOCUMENT ME!
111      */

112     public Scriptable getScope() throws OpenEditException
113     {
114         if (fieldScope == null)
115         {
116             try
117             {
118                 Context context = Context.enter();
119                 fieldScope = context.newObject(getGlobalScope());
120                 fieldScope.setPrototype(getGlobalScope());
121                 fieldScope.setParentScope(null);
122             }
123             catch (Exception JavaDoc e)
124             {
125                 throw new OpenEditException(e);
126             }
127             finally
128             {
129                 Context.exit();
130             }
131         }
132
133         return fieldScope;
134     }
135
136     /**
137      * DOCUMENT ME!
138      *
139      * @param inScript
140      */

141     public void setScript(Script inScript)
142     {
143         fieldScript = inScript;
144     }
145
146     /* (non-Javadoc)
147      * @see com.perf.perfectform.script.ScriptRunner#getScript()
148      */

149     public Script getScript()
150     {
151         return fieldScript;
152     }
153
154     /* (non-Javadoc)
155      * @see com.perf.perfectform.script.ScriptRunner#declareBean(String, Object)
156      *
157      * Assume you have already called Context context = Context.enter();
158      */

159     public void declareBean(String JavaDoc name, Object JavaDoc bean) throws OpenEditException
160     {
161         getScope().put(name, getScope(), Context.toObject(bean, getScope()));
162     }
163
164     /**
165      * @see ScriptRunner#execFunction(String, Object[])
166      */

167     public Object JavaDoc execFunction(String JavaDoc inFuncName) throws OpenEditException
168     {
169         return execFunction(inFuncName, new Object JavaDoc[0]);
170     }
171
172     /**
173      * @see ScriptRunner#execFunction(String, Object[])
174      */

175     public Object JavaDoc execFunction(String JavaDoc inFuncName, Object JavaDoc[] inParameters)
176         throws OpenEditException
177     {
178         try
179         {
180             Context context = Context.enter();
181
182             // See comment above about the context class loader.
183
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
184
185             Object JavaDoc function = getScope().get(inFuncName, getScope());
186
187             if (function instanceof Function)
188             {
189                 LOGGER.debug(
190                     "Evaluating the " + inFuncName + "() function on " +
191                     getScript().getDescription());
192
193                 Object JavaDoc result = ((Function) function).call(context, getScope(), null, inParameters);
194
195                 return unmarshal(result);
196             }
197             else
198             {
199                 LOGGER.debug(
200                     "No " + inFuncName + "() function found on " + getScript().getDescription() +
201                     ", was " + function.toString());
202             }
203         }
204         catch (Exception JavaDoc e)
205         {
206             LOGGER.error("execFunction(): Error during " + inFuncName + "(): " + e.getMessage());
207
208             //e.printStackTrace();
209
throw new OpenEditException(e);
210         }
211         finally
212         {
213             Context.exit();
214         }
215
216         return null;
217     }
218
219     /* (non-Javadoc)
220      * @see com.perf.perfectform.script.ScriptRunner#init()
221      */

222     public void init() throws OpenEditException
223     {
224         if (getScript() != null)
225         {
226             // Run the main script, which contains the calculate() (and
227
// possibly init() ) function definitions.
228
try
229             {
230                 // We need to set the context class loader so that Rhino's
231
// DefiningClassLoader picks it up. In reality, we should
232
// probably set this elsewhere (i.e. where we create the
233
// thread), but we don't really need to right now.
234
if (Thread.currentThread().getContextClassLoader() == getClass().getClassLoader())
235                 {
236                     setInitialized(true);
237                 }
238
239                 Context context = Context.enter();
240
241                 if (!isInitialized())
242                 {
243                     Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
244
245                     context.setOptimizationLevel(-1);
246                 }
247
248                 Script script = getScript();
249
250                 context.evaluateString(
251                     getScope(), script.getScriptText(), script.getDescription(),
252                     script.getStartLineNumber(), null);
253
254                 //LOGGER.info( "Javascript optimization level: " + context.getOptimizationLevel() );
255
}
256             catch (Exception JavaDoc e)
257             {
258                 LOGGER.error("init(): " + e.getMessage());
259
260                 // LOGGER.error(bse);
261
throw new OpenEditException(e);
262             }
263             finally
264             {
265                 Context.exit();
266             }
267         }
268     }
269
270     /* (non-Javadoc)
271      * @see com.perf.perfectform.script.ScriptRunner#terminate()
272      */

273     public void terminate()
274     {
275         setScope(null);
276     }
277
278     protected String JavaDoc makeStringFromCode(String JavaDoc inCode)
279     {
280         if ((inCode.indexOf('"') < 0) && (inCode.indexOf('\\') < 0))
281         {
282             return "\"" + inCode + "\"";
283         }
284
285         StringBuffer JavaDoc sb = new StringBuffer JavaDoc('"');
286
287         for (int i = 0; i < inCode.length(); i++)
288         {
289             char c = inCode.charAt(i);
290
291             switch (c)
292             {
293                 case '"':
294                     sb.append("\\\"");
295
296                     break;
297
298                 case '\\':
299                     sb.append("\\\\");
300
301                     break;
302
303                 default:
304                     sb.append(c);
305
306                     break;
307             }
308         }
309
310         sb.append('"');
311
312         return sb.toString();
313     }
314
315     /**
316      * Unmarshal the given JavaScript object into a Java object.
317      *
318      * @param inObj The JavaScript object
319      *
320      * @return The Java object
321      */

322     protected Object JavaDoc unmarshal(Object JavaDoc inObj)
323     {
324         if (inObj instanceof NativeJavaObject)
325         {
326             return ((NativeJavaObject) inObj).unwrap();
327         }
328
329         if (inObj instanceof NativeArray)
330         {
331             NativeArray array = (NativeArray) inObj;
332             Object JavaDoc[] result = new Object JavaDoc[(int) array.jsGet_length()];
333
334             for (int i = 0; i < array.jsGet_length(); i++)
335             {
336                 result[i] = unmarshal(array.get(i, null));
337             }
338
339             return result;
340         }
341
342         return inObj;
343     }
344 }
345
Popular Tags