diff --git a/src/helma/scripting/rhino/GlobalObject.java b/src/helma/scripting/rhino/GlobalObject.java index 58ea1b8d..5b410ab7 100644 --- a/src/helma/scripting/rhino/GlobalObject.java +++ b/src/helma/scripting/rhino/GlobalObject.java @@ -152,9 +152,7 @@ public class GlobalObject extends ImporterTopLevel implements PropertyRecorder { */ public boolean renderSkin(Object skinobj, Object paramobj) throws UnsupportedEncodingException, IOException { - Context cx = Context.getCurrentContext(); - RequestEvaluator reval = (RequestEvaluator) cx.getThreadLocal("reval"); - RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine"); + RhinoEngine engine = RhinoEngine.getRhinoEngine(); Skin skin; if (skinobj instanceof Wrapper) { @@ -170,7 +168,7 @@ public class GlobalObject extends ImporterTopLevel implements PropertyRecorder { Map param = RhinoCore.getSkinParam(paramobj); if (skin != null) { - skin.render(reval, null, param); + skin.render(engine.reval, null, param); } return true; @@ -186,9 +184,7 @@ public class GlobalObject extends ImporterTopLevel implements PropertyRecorder { */ public String renderSkinAsString(Object skinobj, Object paramobj) throws UnsupportedEncodingException, IOException { - Context cx = Context.getCurrentContext(); - RequestEvaluator reval = (RequestEvaluator) cx.getThreadLocal("reval"); - RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine"); + RhinoEngine engine = RhinoEngine.getRhinoEngine(); Skin skin; if (skinobj instanceof Wrapper) { @@ -204,9 +200,9 @@ public class GlobalObject extends ImporterTopLevel implements PropertyRecorder { Map param = RhinoCore.getSkinParam(paramobj); if (skin != null) { - ResponseTrans res = reval.getResponse(); + ResponseTrans res = engine.getResponse(); res.pushStringBuffer(); - skin.render(reval, null, param); + skin.render(engine.reval, null, param); return res.popStringBuffer(); } diff --git a/src/helma/scripting/rhino/HopObject.java b/src/helma/scripting/rhino/HopObject.java index 138ca864..3e8f3fc8 100644 --- a/src/helma/scripting/rhino/HopObject.java +++ b/src/helma/scripting/rhino/HopObject.java @@ -65,6 +65,7 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco this(className, core); this.node = node; setPrototype(proto); + setParentScope(core.global); } /** @@ -72,10 +73,8 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco * * @param core the RhinoCore * @return the HopObject prototype - * @throws PropertyException */ - public static HopObject init(RhinoCore core) - throws PropertyException { + public static HopObject init(RhinoCore core) { int attributes = DONTENUM | PERMANENT; // create prototype object @@ -197,9 +196,7 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco */ public boolean jsFunction_renderSkin(Object skinobj, Object paramobj) throws UnsupportedEncodingException, IOException { - Context cx = Context.getCurrentContext(); - RequestEvaluator reval = (RequestEvaluator) cx.getThreadLocal("reval"); - RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine"); + RhinoEngine engine = RhinoEngine.getRhinoEngine(); Skin skin; if (skinobj instanceof Wrapper) { @@ -217,7 +214,7 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco checkNode(); if (skin != null) { - skin.render(reval, node, param); + skin.render(engine.reval, node, param); } return true; @@ -232,9 +229,8 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco * @return the resource, if found, null otherwise */ public Object jsFunction_getResource(String resourceName) { - Context cx = Context.getCurrentContext(); - RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine"); - Prototype prototype = engine.core.app.getPrototypeByName(className); + RhinoEngine engine = RhinoEngine.getRhinoEngine(); + Prototype prototype = engine.app.getPrototypeByName(className); while (prototype != null) { Resource[] resources = prototype.getResources(); for (int i = resources.length - 1; i >= 0; i--) { @@ -256,8 +252,7 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco * @return an array of resources with the given name */ public Object jsFunction_getResources(String resourceName) { - Context cx = Context.getCurrentContext(); - RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine"); + RhinoEngine engine = RhinoEngine.getRhinoEngine(); Prototype prototype = engine.core.app.getPrototypeByName(className); ArrayList a = new ArrayList(); while (prototype != null) { @@ -282,9 +277,7 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco */ public String jsFunction_renderSkinAsString(Object skinobj, Object paramobj) throws UnsupportedEncodingException, IOException { - Context cx = Context.getCurrentContext(); - RequestEvaluator reval = (RequestEvaluator) cx.getThreadLocal("reval"); - RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine"); + RhinoEngine engine = RhinoEngine.getRhinoEngine(); Skin skin; if (skinobj instanceof Wrapper) { @@ -302,9 +295,9 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco checkNode(); if (skin != null) { - ResponseTrans res = reval.getResponse(); + ResponseTrans res = engine.getResponse(); res.pushStringBuffer(); - skin.render(reval, node, param); + skin.render(engine.reval, node, param); return res.popStringBuffer(); } @@ -716,6 +709,13 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco // register property for PropertyRecorder interface if (isRecording) { changedProperties.add(name); + if (value instanceof Function) { + // reset function's parent scope, needed because of the way we compile + // prototype code, using the prototype objects as scope + Function f = (Function) value; + if (f.getParentScope() == this) + f.setParentScope(core.global); + } } super.put(name, start, value); } else { diff --git a/src/helma/scripting/rhino/JavaObject.java b/src/helma/scripting/rhino/JavaObject.java index b8cf5411..6b15e1b3 100644 --- a/src/helma/scripting/rhino/JavaObject.java +++ b/src/helma/scripting/rhino/JavaObject.java @@ -77,9 +77,7 @@ public class JavaObject extends NativeJavaObject { */ public boolean renderSkin(Object skinobj, Object paramobj) throws UnsupportedEncodingException, IOException { - Context cx = Context.getCurrentContext(); - RequestEvaluator reval = (RequestEvaluator) cx.getThreadLocal("reval"); - RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine"); + RhinoEngine engine = RhinoEngine.getRhinoEngine(); Skin skin; if (skinobj instanceof Wrapper) { @@ -95,7 +93,7 @@ public class JavaObject extends NativeJavaObject { Map param = RhinoCore.getSkinParam(paramobj); if (skin != null) { - skin.render(reval, javaObject, param); + skin.render(engine.reval, javaObject, param); } return true; @@ -111,9 +109,7 @@ public class JavaObject extends NativeJavaObject { */ public String renderSkinAsString(Object skinobj, Object paramobj) throws UnsupportedEncodingException, IOException { - Context cx = Context.getCurrentContext(); - RequestEvaluator reval = (RequestEvaluator) cx.getThreadLocal("reval"); - RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine"); + RhinoEngine engine = RhinoEngine.getRhinoEngine(); Skin skin; if (skinobj instanceof Wrapper) { @@ -129,9 +125,9 @@ public class JavaObject extends NativeJavaObject { Map param = RhinoCore.getSkinParam(paramobj); if (skin != null) { - ResponseTrans res = reval.getResponse(); + ResponseTrans res = engine.getResponse(); res.pushStringBuffer(); - skin.render(reval, javaObject, param); + skin.render(engine.reval, javaObject, param); return res.popStringBuffer(); } @@ -170,11 +166,7 @@ public class JavaObject extends NativeJavaObject { * Checks whether the given property is defined in this object. */ public boolean has(String name, Scriptable start) { - // System.err.println ("HAS: "+name); - if (overload.containsKey(name)) { - return true; - } - return super.has(name, start); + return overload.containsKey(name) || super.has(name, start); } /** @@ -227,8 +219,7 @@ public class JavaObject extends NativeJavaObject { * @return the resource, if found, null otherwise */ public Object getResource(String resourceName) { - Context cx = Context.getCurrentContext(); - RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine"); + RhinoEngine engine = RhinoEngine.getRhinoEngine(); Prototype prototype = engine.core.app.getPrototypeByName(protoName); while (prototype != null) { Resource[] resources = prototype.getResources(); @@ -251,8 +242,7 @@ public class JavaObject extends NativeJavaObject { * @return an array of resources with the given name */ public Object getResources(String resourceName) { - Context cx = Context.getCurrentContext(); - RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine"); + RhinoEngine engine = RhinoEngine.getRhinoEngine(); Prototype prototype = engine.core.app.getPrototypeByName(protoName); ArrayList a = new ArrayList(); while (prototype != null) { diff --git a/src/helma/scripting/rhino/RhinoCore.java b/src/helma/scripting/rhino/RhinoCore.java index b6bf430f..171f985c 100644 --- a/src/helma/scripting/rhino/RhinoCore.java +++ b/src/helma/scripting/rhino/RhinoCore.java @@ -42,6 +42,9 @@ public final class RhinoCore implements ScopeProvider { // the application we're running in public final Application app; + // our context factory + ContextFactory contextFactory; + // the global object GlobalObject global; @@ -66,17 +69,20 @@ public final class RhinoCore implements ScopeProvider { // Any error that may have been found in global code String globalError; + // the debugger, if active HelmaDebugger debugger = null; + // optimization level for rhino engine, ranges from -1 to 9 + int optLevel = 0; + + // debugger/tracer flags + boolean hasDebugger = false; + boolean hasTracer = false; + // dynamic portion of the type check sleep that grows // as the app remains unchanged long updateSnooze = 500; - static { - ContextFactory.initGlobal(new HelmaContextFactory()); - } - - /** * Create a Rhino evaluator for the given application and request evaluator. */ @@ -84,6 +90,8 @@ public final class RhinoCore implements ScopeProvider { this.app = app; wrappercache = new WeakCacheMap(500); prototypes = new Hashtable(); + contextFactory = new HelmaContextFactory(); + contextFactory.initApplicationClassLoader(app.getClassLoader()); } /** @@ -91,31 +99,27 @@ public final class RhinoCore implements ScopeProvider { * necessary to bootstrap the rest is parsed. */ protected synchronized void initialize() { - Context context = Context.enter(); - context.setCompileFunctionsWithDynamicScope(true); - context.setApplicationClassLoader(app.getClassLoader()); - wrapper = new WrapMaker(); - wrapper.setJavaPrimitiveWrap(false); - context.setWrapFactory(wrapper); - - // Set up visual debugger if rhino.debug = true - if ("true".equals(app.getProperty("rhino.debug"))) { - initDebugger(context); - } + hasDebugger = "true".equalsIgnoreCase(app.getProperty("rhino.debug")); + hasTracer = "true".equalsIgnoreCase(app.getProperty("rhino.trace")); // Set default optimization level according to whether debugger is on - int optLevel = debugger == null ? 0 : -1; - - String opt = app.getProperty("rhino.optlevel"); - if (opt != null) { - try { - optLevel = Integer.parseInt(opt); - } catch (Exception ignore) { - app.logError("Invalid rhino optlevel: " + opt); + if (hasDebugger || hasTracer) { + optLevel = -1; + } else { + String opt = app.getProperty("rhino.optlevel"); + if (opt != null) { + try { + optLevel = Integer.parseInt(opt); + } catch (Exception ignore) { + app.logError("Invalid rhino optlevel: " + opt); + } } } - context.setOptimizationLevel(optLevel); + wrapper = new WrapMaker(); + wrapper.setJavaPrimitiveWrap(false); + + Context context = contextFactory.enter(); try { // create global object @@ -162,29 +166,22 @@ public final class RhinoCore implements ScopeProvider { getPrototype("global"); } catch (Exception e) { - System.err.println("Cannot initialize interpreter"); - System.err.println("Error: " + e); - e.printStackTrace(); + app.logError("Cannot initialize interpreter", e); throw new RuntimeException(e.getMessage(), e); } finally { - Context.exit(); + contextFactory.exit(); } } void initDebugger(Context context) { try { - if (debugger == null) { - debugger = new HelmaDebugger(app.getName()); - debugger.setScopeProvider(this); - // debugger.setScope(global); - debugger.attachTo(context.getFactory()); - // debugger.pack(); - // debugger.getDebugFrame().setLocation(60, 60); - } - // if (!debugger.isVisible()) - // debugger.setVisible(true); + if (debugger == null) { + debugger = new HelmaDebugger(app.getName()); + debugger.setScopeProvider(this); + debugger.attachTo(contextFactory); + } } catch (Exception x) { - x.printStackTrace(); + app.logError("Error setting up debugger", x); } } @@ -235,10 +232,10 @@ public final class RhinoCore implements ScopeProvider { * @param type the info, containing the object proto, last update time and * the set of compiled functions properties */ - private synchronized void evaluatePrototype(TypeInfo type) { + private synchronized void evaluatePrototype(final TypeInfo type) { type.prepareCompilation(); - Prototype prototype = type.frameworkProto; + final Prototype prototype = type.frameworkProto; // set the parent prototype in case it hasn't been done before // or it has changed... @@ -249,12 +246,16 @@ public final class RhinoCore implements ScopeProvider { globalError = null; } - // loop through the prototype's code elements and evaluate them - Iterator code = prototype.getCodeResources(); - while (code.hasNext()) { - evaluate(type, (Resource) code.next()); - } - + contextFactory.call(new ContextAction() { + public Object run(Context cx) { + // loop through the prototype's code elements and evaluate them + Iterator code = prototype.getCodeResources(); + while (code.hasNext()) { + evaluate(cx, type, (Resource) code.next()); + } + return null; + } + }); type.commitCompilation(); } @@ -470,7 +471,7 @@ public final class RhinoCore implements ScopeProvider { * Convert an input argument from Java to the scripting runtime * representation. */ - public Object processXmlRpcArgument (Object what) throws Exception { + public Object processXmlRpcArgument (Object what) { if (what == null) return null; if (what instanceof Vector) { @@ -506,7 +507,7 @@ public final class RhinoCore implements ScopeProvider { /** * convert a JavaScript Object object to a generic Java object stucture. */ - public Object processXmlRpcResponse (Object what) throws Exception { + public Object processXmlRpcResponse (Object what) { // unwrap if argument is a Wrapper if (what instanceof Wrapper) { what = ((Wrapper) what).unwrap(); @@ -606,9 +607,7 @@ public final class RhinoCore implements ScopeProvider { HopObject hobj = (HopObject) wrappercache.get(n); if (hobj == null) { - String protoname = n.getPrototype(); - Scriptable op = getValidPrototype(protoname); // no prototype found for this node @@ -630,7 +629,6 @@ public final class RhinoCore implements ScopeProvider { } hobj = new HopObject(protoname, this, n, op); - wrappercache.put(n, hobj); } @@ -652,12 +650,11 @@ public final class RhinoCore implements ScopeProvider { if (hasFunction(proto, hrefFunction)) { // get the currently active rhino engine and invoke the function - Context cx = Context.getCurrentContext(); - RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine"); + RhinoEngine eng = RhinoEngine.getRhinoEngine(); Object result; try { - result = engine.invoke(handler, hrefFunction, + result = eng.invoke(handler, hrefFunction, new Object[] { basicHref }, ScriptingEngine.ARGS_WRAP_DEFAULT, false); @@ -689,14 +686,13 @@ public final class RhinoCore implements ScopeProvider { Skin skin = null; Object handler = obj; // get the currently active rhino engine and render the skin - Context cx = Context.getCurrentContext(); - RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine"); + RhinoEngine eng = RhinoEngine.getRhinoEngine(); while (handler != null) { Prototype proto = app.getPrototype(handler); if (proto != null) { - skin = engine.getSkin(proto.getName(), hrefSkin); + skin = eng.getSkin(proto.getName(), hrefSkin); } if (skin != null) { @@ -707,18 +703,27 @@ public final class RhinoCore implements ScopeProvider { } if (skin != null) { - engine.getResponse().pushStringBuffer(); + eng.getResponse().pushStringBuffer(); HashMap param = new HashMap(); param.put("path", basicHref); - skin.render(engine.getRequestEvaluator(), handler, param); + skin.render(eng.getRequestEvaluator(), handler, param); - basicHref = engine.getResponse().popStringBuffer().trim(); + basicHref = eng.getResponse().popStringBuffer().trim(); } } return basicHref; } + /** + * Get the RhinoCore instance associated with the current thread, or null + * @return the RhinoCore instance associated with the current thread + */ + public static RhinoCore getCore() { + RhinoEngine eng = RhinoEngine.getRhinoEngine(); + return eng != null ? eng.core : null; + } + ///////////////////////////////////////////// // skin related methods ///////////////////////////////////////////// @@ -766,30 +771,30 @@ public final class RhinoCore implements ScopeProvider { * @param typename the type this resource belongs to * @param code a code resource */ - public void injectCodeResource(String typename, Resource code) { - TypeInfo type = (TypeInfo) prototypes.get(typename.toLowerCase()); + public void injectCodeResource(String typename, final Resource code) { + final TypeInfo type = (TypeInfo) prototypes.get(typename.toLowerCase()); if (type == null || type.lastUpdate == -1) return; - evaluate(type, code); + contextFactory.call(new ContextAction() { + public Object run(Context cx) { + evaluate(cx, type, code); + return null; + } + }); } //////////////////////////////////////////////// // private evaluation/compilation methods //////////////////////////////////////////////// - - private synchronized void evaluate (TypeInfo type, Resource code) { - // get the current context - Context cx = Context.getCurrentContext(); - + private synchronized void evaluate(Context cx, TypeInfo type, Resource code) { String sourceName = code.getName(); Reader reader = null; - + Resource previousCurrentResource = app.getCurrentCodeResource(); app.setCurrentCodeResource(code); try { Scriptable op = type.objProto; - // do the update, evaluating the file if (sourceName.endsWith(".js")) { reader = new InputStreamReader(code.getInputStream()); @@ -805,11 +810,12 @@ public final class RhinoCore implements ScopeProvider { } } catch (Exception e) { - app.logError("Error parsing file " + sourceName, e); + ScriptingException sx = new ScriptingException(e.getMessage(), e); + app.logError("Error parsing file " + sourceName, sx); // mark prototype as broken if (type.error == null) { type.error = e.getMessage(); - if (type.error == null || e instanceof EcmaError) { + if (type.error == null) { type.error = e.toString(); } if ("global".equals(type.frameworkProto.getLowerCaseName())) { @@ -817,7 +823,6 @@ public final class RhinoCore implements ScopeProvider { } wrappercache.clear(); } - // e.printStackTrace(); } finally { app.setCurrentCodeResource(previousCurrentResource); if (reader != null) { @@ -931,7 +936,7 @@ public final class RhinoCore implements ScopeProvider { objProto.setAttributes(key, 0); objProto.delete(key); } catch (Exception px) { - System.err.println("Error unsetting property "+key+" on "+ + app.logEvent("Error unsetting property "+key+" on "+ frameworkProto.getName()); } } @@ -1036,7 +1041,6 @@ public final class RhinoCore implements ScopeProvider { } public Scriptable wrapNewObject(Context cx, Scriptable scope, Object obj) { - // System.err.println ("N-Wrapping: "+obj); if (obj instanceof INode) { return getNodeWrapper((INode) obj); } @@ -1092,13 +1096,30 @@ public final class RhinoCore implements ScopeProvider { } } -} + class HelmaContextFactory extends ContextFactory { -class HelmaContextFactory extends ContextFactory { - protected boolean hasFeature(Context cx, int featureIndex) { - if (featureIndex == Context.FEATURE_DYNAMIC_SCOPE) { - return true; + final boolean strictVars = "true".equalsIgnoreCase(app.getProperty("strictVars")); + + protected void onContextCreated(Context cx) { + cx.setWrapFactory(wrapper); + cx.setOptimizationLevel(optLevel); + // Set up visual debugger if rhino.debug = true + if (hasDebugger) + initDebugger(cx); + super.onContextCreated(cx); } - return super.hasFeature(cx, featureIndex); + + protected boolean hasFeature(Context cx, int featureIndex) { + switch (featureIndex) { + case Context.FEATURE_DYNAMIC_SCOPE: + return true; + + case Context.FEATURE_STRICT_VARS: + return strictVars; + + default: + return super.hasFeature(cx, featureIndex); + } + } } } diff --git a/src/helma/scripting/rhino/RhinoEngine.java b/src/helma/scripting/rhino/RhinoEngine.java index ccea3cd8..adc9477a 100644 --- a/src/helma/scripting/rhino/RhinoEngine.java +++ b/src/helma/scripting/rhino/RhinoEngine.java @@ -54,6 +54,8 @@ public class RhinoEngine implements ScriptingEngine { // the request evaluator instance owning this fesi evaluator RequestEvaluator reval; + + // the rhino core RhinoCore core; // remember global variables from last invokation to be able to @@ -66,6 +68,9 @@ public class RhinoEngine implements ScriptingEngine { // the thread currently running this engine Thread thread; + // thread local engine registry + static ThreadLocal engines = new ThreadLocal(); + // the introspector that provides documentation for this application DocApplication doc = null; @@ -83,9 +88,8 @@ public class RhinoEngine implements ScriptingEngine { this.app = app; this.reval = reval; initRhinoCore(app); - context = Context.enter(); - context.setCompileFunctionsWithDynamicScope(true); - context.setApplicationClassLoader(app.getClassLoader()); + + context = core.contextFactory.enter(); try { global = new GlobalObject(core, app, true); @@ -105,22 +109,27 @@ public class RhinoEngine implements ScriptingEngine { extensionGlobals.putAll(tmpGlobals); } } catch (ConfigurationException e) { - app.logEvent("Couldn't initialize extension " + ext.getName() + ": " + - e.getMessage()); + app.logError("Couldn't initialize extension " + ext.getName(), e); } } } } catch (Exception e) { - System.err.println("Cannot initialize interpreter"); - System.err.println("Error: " + e); - e.printStackTrace(); - throw new RuntimeException(e.getMessage()); + app.logError("Cannot initialize interpreter", e); + throw new RuntimeException(e.getMessage(), e); } finally { - Context.exit (); + core.contextFactory.exit (); } } + /** + * Return the RhinoEngine associated with the current thread, or null. + * @return the RhinoEngine assocated with the current thread + */ + public static RhinoEngine getRhinoEngine() { + return (RhinoEngine) engines.get(); + } + /** * Initialize the RhinoCore instance for this engine and application. * @param app the application we belong to @@ -145,39 +154,20 @@ public class RhinoEngine implements ScriptingEngine { * engine know it should update its prototype information. */ public void updatePrototypes() throws IOException { - // remember the current thread as our thread - we this here so + // remember the current thread as our thread - we do this here so // the thread is already set when the RequestEvaluator calls // Application.getDataRoot(), which may result in a function invocation // (chicken and egg problem, kind of) thread = Thread.currentThread(); - context = Context.enter(); - context.setCompileFunctionsWithDynamicScope(true); - context.setApplicationClassLoader(app.getClassLoader()); - context.setWrapFactory(core.wrapper); + context = core.contextFactory.enter(); - // if visual debugger is on let it know we're entering a context - if (core.debugger != null) { - core.initDebugger(context); - } - - if ("true".equals(app.getProperty("rhino.trace"))) { + if (core.hasTracer) { context.setDebugger(new Tracer(getResponse()), null); } - // Set default optimization level according to whether debugger is on - int optLevel = core.debugger == null ? 0 : -1; - - try { - optLevel = Integer.parseInt(app.getProperty("rhino.optlevel")); - } catch (Exception ignore) { - // use default opt-level - } - - context.setOptimizationLevel(optLevel); - // register the per-thread scope with the dynamic scope - context.putThreadLocal("reval", reval); - context.putThreadLocal("engine", this); + // register the engine with the current thread + engines.set(this); // update prototypes core.updatePrototypes(); } @@ -224,10 +214,9 @@ public class RhinoEngine implements ScriptingEngine { * execution context has terminated. */ public synchronized void exitContext() { - context.removeThreadLocal("reval"); - context.removeThreadLocal("engine"); - Context.exit(); - // core.global.unregisterScope(); + // unregister the engine threadlocal + engines.remove(); + core.contextFactory.exit(); thread = null; // loop through previous globals and unset them, if necessary. @@ -237,7 +226,7 @@ public class RhinoEngine implements ScriptingEngine { try { global.delete(g); } catch (Exception x) { - System.err.println("Error resetting global property: " + g); + app.logEvent("Error unsetting global property: " + g); } } lastGlobals = null; @@ -265,23 +254,7 @@ public class RhinoEngine implements ScriptingEngine { public Object invoke(Object thisObject, String functionName, Object[] args, int argsWrapMode, boolean resolve) throws ScriptingException { try { - for (int i = 0; i < args.length; i++) { - switch (argsWrapMode) { - case ARGS_WRAP_DEFAULT: - // convert java objects to JavaScript - if (args[i] != null) { - args[i] = Context.javaToJS(args[i], global); - } - break; - case ARGS_WRAP_XMLRPC: - // XML-RPC requires special argument conversion - args[i] = core.processXmlRpcArgument(args[i]); - break; - } - - } Scriptable obj = thisObject == null ? global : Context.toObject(thisObject, global); - // if function name should be resolved interpret it as member expression, // otherwise replace dots with underscores. if (resolve) { @@ -308,7 +281,23 @@ public class RhinoEngine implements ScriptingEngine { return null; } - Object retval = ((Function) f).call(context, global, obj, args); + for (int i = 0; i < args.length; i++) { + switch (argsWrapMode) { + case ARGS_WRAP_DEFAULT: + // convert java objects to JavaScript + if (args[i] != null) { + args[i] = Context.javaToJS(args[i], global); + } + break; + case ARGS_WRAP_XMLRPC: + // XML-RPC requires special argument conversion + args[i] = core.processXmlRpcArgument(args[i]); + break; + } + } + + // use Context.call() in order to set the context's factory + Object retval = Context.call(core.contextFactory, (Function)f, global, obj, args); if (retval instanceof Wrapper) { retval = ((Wrapper) retval).unwrap(); @@ -449,7 +438,6 @@ public class RhinoEngine implements ScriptingEngine { return prop; } } catch (Exception esx) { - // System.err.println ("Error in getProperty: "+esx); return null; } } @@ -479,7 +467,7 @@ public class RhinoEngine implements ScriptingEngine { * @throws java.io.IOException */ public void serialize(Object obj, OutputStream out) throws IOException { - Context.enter(); + core.contextFactory.enter(); try { // use a special ScriptableOutputStream that unwraps Wrappers ScriptableOutputStream sout = new ScriptableOutputStream(out, core.global) { @@ -492,7 +480,7 @@ public class RhinoEngine implements ScriptingEngine { sout.writeObject(obj); sout.flush(); } finally { - Context.exit(); + core.contextFactory.exit(); } } @@ -506,12 +494,12 @@ public class RhinoEngine implements ScriptingEngine { * @throws java.io.IOException */ public Object deserialize(InputStream in) throws IOException, ClassNotFoundException { - Context.enter(); + core.contextFactory.enter(); try { ObjectInputStream sin = new ScriptableInputStream(in, core.global); return sin.readObject(); } finally { - Context.exit(); + core.contextFactory.exit(); } } diff --git a/src/helma/scripting/rhino/extensions/XmlRpcObject.java b/src/helma/scripting/rhino/extensions/XmlRpcObject.java index 1aab5d12..2ab43f10 100644 --- a/src/helma/scripting/rhino/extensions/XmlRpcObject.java +++ b/src/helma/scripting/rhino/extensions/XmlRpcObject.java @@ -54,7 +54,7 @@ public class XmlRpcObject extends BaseFunction { this.method = method; } - /** + /** * This method is used as HopObject constructor from JavaScript. */ public static Object xmlrpcObjectConstructor(Context cx, Object[] args, @@ -106,20 +106,18 @@ public class XmlRpcObject extends BaseFunction { throw new EvaluatorException("Invalid method name"); } - RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine"); - RhinoCore c = engine.getCore(); + RhinoCore core = RhinoCore.getCore(); Scriptable retval = null; try { - retval = Context.getCurrentContext().newObject(c.getScope()); + retval = Context.getCurrentContext().newObject(core.getScope()); XmlRpcClient client = new XmlRpcClient(url); - // long now = System.currentTimeMillis (); int l = args.length; Vector v = new Vector(); for (int i = 0; i < l; i++) { - Object arg = c.processXmlRpcResponse(args[i]); + Object arg = core.processXmlRpcResponse(args[i]); v.addElement(arg); } @@ -129,7 +127,7 @@ public class XmlRpcObject extends BaseFunction { if (result instanceof Exception) { throw (Exception) result; } - retval.put("result", retval, c.processXmlRpcArgument(result)); + retval.put("result", retval, core.processXmlRpcArgument(result)); } catch (Exception x) { String msg = x.getMessage();