diff --git a/src/helma/scripting/rhino/DynamicGlobalObject.java b/src/helma/scripting/rhino/DynamicGlobalObject.java new file mode 100644 index 00000000..82da0685 --- /dev/null +++ b/src/helma/scripting/rhino/DynamicGlobalObject.java @@ -0,0 +1,58 @@ +/* + * Helma License Notice + * + * The contents of this file are subject to the Helma License + * Version 2.0 (the "License"). You may not use this file except in + * compliance with the License. A copy of the License is available at + * http://adele.helma.org/download/helma/license.txt + * + * Copyright 1998-2003 Helma Software. All Rights Reserved. + * + * $RCSfile$ + * $Author$ + * $Revision$ + * $Date$ + */ + +package helma.scripting.rhino; + +import helma.framework.core.Application; +import org.mozilla.javascript.Scriptable; +import java.util.WeakHashMap; + +/** + * This class implements a global scope object that is a dynamic proxy + * to a shared global scope and a per-thread dynamic scope. + */ +public class DynamicGlobalObject extends GlobalObject { + + WeakHashMap map = new WeakHashMap(); + + public DynamicGlobalObject(RhinoCore core, Application app) { + super(core, app); + } + + public Object get(String s, Scriptable scriptable) { + Object obj = super.get(s, scriptable); + if (obj != null && obj != NOT_FOUND) + return obj; + Scriptable scope = getScope(); + if (scope != null) { + return scope.get(s, scope); + } + return NOT_FOUND; + } + + public void registerScope(Scriptable scope) { + map.put(Thread.currentThread(), scope); + } + + public Scriptable unregisterScope() { + return (Scriptable) map.remove(Thread.currentThread()); + } + + public final Scriptable getScope() { + return (Scriptable) map.get(Thread.currentThread()); + } + +} diff --git a/src/helma/scripting/rhino/RhinoCore.java b/src/helma/scripting/rhino/RhinoCore.java index 76a087af..3a55c894 100644 --- a/src/helma/scripting/rhino/RhinoCore.java +++ b/src/helma/scripting/rhino/RhinoCore.java @@ -37,7 +37,7 @@ public final class RhinoCore { public final Application app; // the global object - GlobalObject global; + DynamicGlobalObject global; // caching table for JavaScript object wrappers CacheMap wrappercache; @@ -88,10 +88,10 @@ public final class RhinoCore { context.setOptimizationLevel(optLevel); try { - GlobalObject g = new GlobalObject(this, app); + DynamicGlobalObject g = new DynamicGlobalObject(this, app); g.init(); - global = (GlobalObject) context.initStandardObjects(g); + global = (DynamicGlobalObject) context.initStandardObjects(g); pathProto = new PathWrapper(this); @@ -568,15 +568,6 @@ public final class RhinoCore { String protoname = n.getPrototype(); - // set the DbMapping of the node according to its prototype. - // this *should* be done on the objectmodel level, but isn't currently - // for embedded nodes since there's not enough type info at the objectmodel level - // for those nodes. - /* if ((protoname != null) && (protoname.length() > 0) && - (n.getDbMapping() == null)) { - n.setDbMapping(app.getDbMapping(protoname)); - } */ - Scriptable op = null; op = getValidPrototype(protoname); @@ -761,6 +752,8 @@ public final class RhinoCore { private synchronized void updateEvaluator(TypeInfo type, Reader reader, String sourceName, int firstline) { // System.err.println("UPDATE EVALUATOR: "+prototype+" - "+sourceName); + Scriptable threadScope = global.unregisterScope(); + try { // get the current context Context cx = Context.getCurrentContext(); @@ -794,6 +787,9 @@ public final class RhinoCore { // shouldn't happen } } + if (threadScope != null) { + global.registerScope(threadScope); + } } } diff --git a/src/helma/scripting/rhino/RhinoEngine.java b/src/helma/scripting/rhino/RhinoEngine.java index f7d65577..fb5ac5a0 100644 --- a/src/helma/scripting/rhino/RhinoEngine.java +++ b/src/helma/scripting/rhino/RhinoEngine.java @@ -44,7 +44,7 @@ public class RhinoEngine implements ScriptingEngine { // The Rhino context Context context; - // the global object + // the per-thread global object Scriptable global; // the request evaluator instance owning this fesi evaluator @@ -82,7 +82,7 @@ public class RhinoEngine implements ScriptingEngine { context.setApplicationClassLoader(app.getClassLoader()); try { - global = new GlobalObject(core, app); // context.newObject(core.global); + global = new GlobalObject(core, app); global.setPrototype(core.global); global.setParentScope(null); @@ -162,6 +162,9 @@ public class RhinoEngine implements ScriptingEngine { } context.setOptimizationLevel(optLevel); + // register the per-thread scope with the dynamic scope + core.global.registerScope(global); + // update prototypes core.updatePrototypes(); context.putThreadLocal("reval", reval); context.putThreadLocal("engine", this); @@ -216,6 +219,7 @@ public class RhinoEngine implements ScriptingEngine { context.removeThreadLocal("reval"); context.removeThreadLocal("engine"); Context.exit(); + core.global.unregisterScope(); thread = null; // loop through previous globals and unset them, if necessary.