* Do not use Context.setCompileFunctionsWithDynamicScope() as it is

seriously BROKEN for nested functions.
  The only workaround needed is a little fix in HopObject.put() to set the
  parent scope on functions because of the funky way we compile prototypes.
* Use one ContextFactory instance per RhinoCore to initialize, enter and exit
  contexts, and use various call() methods to actually use it in RhinoCore.evaluate()
  and RhinoEngine.invoke().
* Set parent scope in HopObject constructor.
* Use java.lang.ThreadLocal to implement engine/thread registration.
* Implement RhinoCore.getRhinoCore() and RhinoEngine.getRhinoEngine().
* Implement rhino.strictvars to throw errors on undeclared vars.
* Do not declare throws Exception in RhinoCore.processXmlRpc* methods.
* Clean up error logging.
This commit is contained in:
hns 2006-12-20 21:52:22 +00:00
parent 68756f4b3e
commit 20354228a2
6 changed files with 188 additions and 195 deletions

View file

@ -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();
}

View file

@ -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 {

View file

@ -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) {

View file

@ -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);
}
}
}
}

View file

@ -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();
}
}

View file

@ -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();