diff --git a/src/helma/framework/core/RequestEvaluator.java b/src/helma/framework/core/RequestEvaluator.java index af2a3014..09795ec5 100644 --- a/src/helma/framework/core/RequestEvaluator.java +++ b/src/helma/framework/core/RequestEvaluator.java @@ -330,8 +330,6 @@ public final class RequestEvaluator implements Runnable { // set the req.action property, cutting off the _action suffix req.setAction(action); - // make sure we have a valid function name by replacing dots with underscores - action = action.replace('.', '_'); // reset skin recursion detection counter skinDepth = 0; @@ -344,7 +342,8 @@ public final class RequestEvaluator implements Runnable { scriptingEngine.invoke(currentElement, "onRequest", new Object[0], - ScriptingEngine.ARGS_WRAP_DEFAULT); + ScriptingEngine.ARGS_WRAP_DEFAULT, + false); } } catch (RedirectException redir) { throw redir; @@ -360,13 +359,18 @@ public final class RequestEvaluator implements Runnable { .getInputStream()); Vector args = xreq.getParameters(); args.add(0, xreq.getMethodName()); - result = scriptingEngine.invoke(currentElement, action, - args.toArray(), ScriptingEngine.ARGS_WRAP_XMLRPC); + result = scriptingEngine.invoke(currentElement, + action, + args.toArray(), + ScriptingEngine.ARGS_WRAP_XMLRPC, + false); res.writeXmlRpcResponse(result); } else { - scriptingEngine.invoke(currentElement, action, - new Object[0], - ScriptingEngine.ARGS_WRAP_DEFAULT); + scriptingEngine.invoke(currentElement, + action, + new Object[0], + ScriptingEngine.ARGS_WRAP_DEFAULT, + false); } } catch (RedirectException redirect) { // if there is a message set, save it on the user object for the next request @@ -420,8 +424,10 @@ public final class RequestEvaluator implements Runnable { // reset skin recursion detection counter skinDepth = 0; - result = scriptingEngine.invoke(currentElement, functionName, args, - ScriptingEngine.ARGS_WRAP_XMLRPC); + result = scriptingEngine.invoke(currentElement, + functionName, args, + ScriptingEngine.ARGS_WRAP_XMLRPC, + false); commitTransaction(); } catch (Exception x) { abortTransaction(); @@ -475,8 +481,11 @@ public final class RequestEvaluator implements Runnable { // reset skin recursion detection counter skinDepth = 0; - result = scriptingEngine.invoke(thisObject, functionName, args, - ScriptingEngine.ARGS_WRAP_DEFAULT); + result = scriptingEngine.invoke(thisObject, + functionName, + args, + ScriptingEngine.ARGS_WRAP_DEFAULT, + true); commitTransaction(); } catch (Exception x) { abortTransaction(); @@ -836,7 +845,8 @@ public final class RequestEvaluator implements Runnable { */ public Object invokeDirectFunction(Object obj, String functionName, Object[] args) throws Exception { - return scriptingEngine.invoke(obj, functionName, args, ScriptingEngine.ARGS_WRAP_DEFAULT); + return scriptingEngine.invoke(obj, functionName, args, + ScriptingEngine.ARGS_WRAP_DEFAULT, false); } /** @@ -961,7 +971,7 @@ public final class RequestEvaluator implements Runnable { private Object getChildElement(Object obj, String name) throws ScriptingException { if (scriptingEngine.hasFunction(obj, "getChildElement")) { return scriptingEngine.invoke(obj, "getChildElement", new Object[] {name}, - ScriptingEngine.ARGS_WRAP_DEFAULT); + ScriptingEngine.ARGS_WRAP_DEFAULT, false); } if (obj instanceof IPathElement) { diff --git a/src/helma/scripting/ScriptingEngine.java b/src/helma/scripting/ScriptingEngine.java index a1503f84..39c2a644 100644 --- a/src/helma/scripting/ScriptingEngine.java +++ b/src/helma/scripting/ScriptingEngine.java @@ -88,12 +88,14 @@ public interface ScriptingEngine { * one of ARGS_WRAP_NONE, * ARGS_WRAP_DEFAULT, * ARGS_WRAP_XMLRPC + * @param resolve indicates whether functionName may contain an object path + * or just the plain function name * @return the return value of the function * @throws ScriptingException to indicate something went wrong * with the invocation */ public Object invoke(Object thisObject, String functionName, - Object[] args, int argsWrapMode) + Object[] args, int argsWrapMode, boolean resolve) throws ScriptingException; diff --git a/src/helma/scripting/rhino/HopObject.java b/src/helma/scripting/rhino/HopObject.java index a75987de..bacb2f16 100644 --- a/src/helma/scripting/rhino/HopObject.java +++ b/src/helma/scripting/rhino/HopObject.java @@ -147,7 +147,10 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco hobj.init(core, node); if (proto != null) { - engine.invoke(hobj, "__constructor__", args, ScriptingEngine.ARGS_WRAP_NONE); + engine.invoke(hobj, + "__constructor__", + args, ScriptingEngine.ARGS_WRAP_NONE, + false); } return hobj; diff --git a/src/helma/scripting/rhino/PhantomEngine.java b/src/helma/scripting/rhino/PhantomEngine.java index 070798d3..8127e310 100644 --- a/src/helma/scripting/rhino/PhantomEngine.java +++ b/src/helma/scripting/rhino/PhantomEngine.java @@ -28,11 +28,27 @@ import helma.scripting.ScriptingException; * @see helma.main.launcher.FilteredClassLoader */ public final class PhantomEngine extends RhinoEngine { + /** + * Invoke a function on some object, using the given arguments and global vars. + * XML-RPC calls require special input and output parameter conversion. * + * @param thisObject the object to invoke the function on, or null for + * global functions + * @param functionName the name of the function to be invoked + * @param args array of argument objects + * @param argsWrapMode indicated the way to process the arguments. Must be + * one of ARGS_WRAP_NONE, + * ARGS_WRAP_DEFAULT, + * ARGS_WRAP_XMLRPC + * @param resolve indicates whether functionName may contain an object path + * or just the plain function name + * @return the return value of the function + * @throws ScriptingException to indicate something went wrong + * with the invocation */ public Object invoke(Object thisObject, String functionName, Object[] args, - int argsWrapMode) throws ScriptingException { - return super.invoke(thisObject, functionName, args, argsWrapMode); + int argsWrapMode, boolean resolve) throws ScriptingException { + return super.invoke(thisObject, functionName, args, argsWrapMode, resolve); } } diff --git a/src/helma/scripting/rhino/RhinoCore.java b/src/helma/scripting/rhino/RhinoCore.java index 72b62153..be864b46 100644 --- a/src/helma/scripting/rhino/RhinoCore.java +++ b/src/helma/scripting/rhino/RhinoCore.java @@ -678,7 +678,8 @@ public final class RhinoCore implements ScopeProvider { try { result = engine.invoke(handler, hrefFunction, new Object[] { basicHref }, - ScriptingEngine.ARGS_WRAP_DEFAULT); + ScriptingEngine.ARGS_WRAP_DEFAULT, + false); } catch (ScriptingException x) { throw new EvaluatorException("Error in hrefFunction: " + x); } diff --git a/src/helma/scripting/rhino/RhinoEngine.java b/src/helma/scripting/rhino/RhinoEngine.java index e1d4d8ff..00316fc6 100644 --- a/src/helma/scripting/rhino/RhinoEngine.java +++ b/src/helma/scripting/rhino/RhinoEngine.java @@ -255,16 +255,24 @@ public class RhinoEngine implements ScriptingEngine { /** * Invoke a function on some object, using the given arguments and global vars. + * XML-RPC calls require special input and output parameter conversion. + * + * @param thisObject the object to invoke the function on, or null for + * global functions + * @param functionName the name of the function to be invoked + * @param args array of argument objects + * @param argsWrapMode indicated the way to process the arguments. Must be + * one of ARGS_WRAP_NONE, + * ARGS_WRAP_DEFAULT, + * ARGS_WRAP_XMLRPC + * @param resolve indicates whether functionName may contain an object path + * or just the plain function name + * @return the return value of the function + * @throws ScriptingException to indicate something went wrong + * with the invocation */ public Object invoke(Object thisObject, String functionName, Object[] args, - int argsWrapMode) throws ScriptingException { - Scriptable eso = null; - - if (thisObject == null) { - eso = global; - } else { - eso = Context.toObject(thisObject, global); - } + int argsWrapMode, boolean resolve) throws ScriptingException { try { for (int i = 0; i < args.length; i++) { switch (argsWrapMode) { @@ -279,15 +287,37 @@ public class RhinoEngine implements ScriptingEngine { args[i] = core.processXmlRpcArgument(args[i]); break; } - } - Object f = ScriptableObject.getProperty(eso, functionName.replace('.', '_')); + } + 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) { + if (functionName.indexOf('.') > 0) { + StringTokenizer st = new StringTokenizer(functionName, "."); + for (int i=0; i