Added support for encoding and decoding XML-RPC parameters.

This commit is contained in:
hns 2002-09-12 17:09:50 +00:00
parent 3c561e4003
commit 7c759d694f
4 changed files with 108 additions and 12 deletions

View file

@ -233,7 +233,7 @@ public final class RequestEvaluator implements Runnable {
// try calling onRequest() function on object before // try calling onRequest() function on object before
// calling the actual action // calling the actual action
try { try {
scriptingEngine.invoke (currentElement, "onRequest", new Object[0]); scriptingEngine.invoke (currentElement, "onRequest", new Object[0], false);
} catch (RedirectException redir) { } catch (RedirectException redir) {
throw redir; throw redir;
} catch (Exception ignore) { } catch (Exception ignore) {
@ -241,7 +241,7 @@ public final class RequestEvaluator implements Runnable {
} }
// do the actual action invocation // do the actual action invocation
scriptingEngine.invoke (currentElement, action, new Object[0]); scriptingEngine.invoke (currentElement, action, new Object[0], false);
localrtx.timer.endEvent (txname+" execute"); localrtx.timer.endEvent (txname+" execute");
} catch (RedirectException redirect) { } catch (RedirectException redirect) {
@ -347,7 +347,7 @@ public final class RequestEvaluator implements Runnable {
String proto = app.getPrototypeName (currentElement); String proto = app.getPrototypeName (currentElement);
app.checkXmlRpcAccess (proto, method); app.checkXmlRpcAccess (proto, method);
result = scriptingEngine.invoke (currentElement, method, args); result = scriptingEngine.invoke (currentElement, method, args, true);
commitTransaction (); commitTransaction ();
} catch (Exception wrong) { } catch (Exception wrong) {
@ -397,7 +397,7 @@ public final class RequestEvaluator implements Runnable {
scriptingEngine.enterContext (globals); scriptingEngine.enterContext (globals);
result = scriptingEngine.invoke (thisObject, method, args); result = scriptingEngine.invoke (thisObject, method, args, false);
commitTransaction (); commitTransaction ();
} catch (Exception wrong) { } catch (Exception wrong) {
@ -538,7 +538,7 @@ public final class RequestEvaluator implements Runnable {
} }
public Object invokeDirectFunction (Object obj, String functionName, Object[] args) throws Exception { public Object invokeDirectFunction (Object obj, String functionName, Object[] args) throws Exception {
return scriptingEngine.invoke (obj, functionName, args); return scriptingEngine.invoke (obj, functionName, args, false);
} }
public synchronized Object invokeFunction (Object object, String functionName, Object[] args) public synchronized Object invokeFunction (Object object, String functionName, Object[] args)

View file

@ -322,7 +322,7 @@ public final class Skin {
int oldLength = reval.res.getBufferLength (); int oldLength = reval.res.getBufferLength ();
if (reval.scriptingEngine.hasFunction (handlerObject, name+"_macro")) { if (reval.scriptingEngine.hasFunction (handlerObject, name+"_macro")) {
// System.err.println ("Getting macro from function"); // System.err.println ("Getting macro from function");
v = reval.scriptingEngine.invoke (handlerObject, name+"_macro", arguments); v = reval.scriptingEngine.invoke (handlerObject, name+"_macro", arguments, false);
} else { } else {
// System.err.println ("Getting macro from property"); // System.err.println ("Getting macro from property");
v = reval.scriptingEngine.get (handlerObject, name); v = reval.scriptingEngine.get (handlerObject, name);
@ -353,7 +353,7 @@ public final class Skin {
throw timeout; throw timeout;
} catch (Exception x) { } catch (Exception x) {
x.printStackTrace(); x.printStackTrace();
String msg = "[HopMacro error: "+x+"]"; String msg = "[HopMacro error in "+this+": "+x+"]";
reval.res.write (" "+msg+" "); reval.res.write (" "+msg+" ");
app.logEvent (msg); app.logEvent (msg);
} }

View file

@ -37,9 +37,10 @@ public interface ScriptingEngine {
/** /**
* Invoke a function on some object, using the given arguments and global vars. * Invoke a function on some object, using the given arguments and global vars.
* XML-RPC calls require special input and output parameter conversion.
*/ */
public Object invoke (Object thisObject, String functionName, Object[] args) public Object invoke (Object thisObject, String functionName, Object[] args, boolean xmlrpc)
throws ScriptingException; throws ScriptingException;
/** /**

View file

@ -373,7 +373,7 @@ public final class FesiEvaluator implements ScriptingEngine {
/** /**
* Invoke a function on some object, using the given arguments and global vars. * Invoke a function on some object, using the given arguments and global vars.
*/ */
public Object invoke (Object thisObject, String functionName, Object[] args) throws ScriptingException { public Object invoke (Object thisObject, String functionName, Object[] args, boolean xmlrpc) throws ScriptingException {
ESObject eso = null; ESObject eso = null;
if (thisObject == null) if (thisObject == null)
eso = global; eso = global;
@ -382,15 +382,23 @@ public final class FesiEvaluator implements ScriptingEngine {
try { try {
ESValue[] esv = args == null ? new ESValue[0] : new ESValue[args.length]; ESValue[] esv = args == null ? new ESValue[0] : new ESValue[args.length];
for (int i=0; i<esv.length; i++) { for (int i=0; i<esv.length; i++) {
// XML-RPC requires special argument conversion
if (xmlrpc)
esv[i] = processXmlRpcArgument (args[i]);
// for java.util.Map objects, we use the special "tight" wrapper // for java.util.Map objects, we use the special "tight" wrapper
// that makes the Map look like a native object // that makes the Map look like a native object
if (args[i] instanceof Map) else if (args[i] instanceof Map)
esv[i] = new ESMapWrapper (this, (Map) args[i]); esv[i] = new ESMapWrapper (this, (Map) args[i]);
else else
esv[i] = ESLoader.normalizeValue (args[i], evaluator); esv[i] = ESLoader.normalizeValue (args[i], evaluator);
} }
ESValue retval = eso.doIndirectCall (evaluator, eso, functionName, esv); ESValue retval = eso.doIndirectCall (evaluator, eso, functionName, esv);
return retval == null ? null : retval.toJavaObject (); if (xmlrpc)
return processXmlRpcResponse (retval);
else if (retval == null)
return null;
else
return retval.toJavaObject ();
} catch (Exception x) { } catch (Exception x) {
// check if this is a redirect exception, which has been converted by fesi // check if this is a redirect exception, which has been converted by fesi
// into an EcmaScript exception, which is why we can't explicitly catch it // into an EcmaScript exception, which is why we can't explicitly catch it
@ -485,6 +493,93 @@ public final class FesiEvaluator implements ScriptingEngine {
return null; return null;
} }
/**
* Convert an input argument from Java to the scripting runtime
* representation.
*/
private ESValue processXmlRpcArgument (Object what) throws Exception {
if (what == null)
return ESNull.theNull;
if (what instanceof Vector) {
Vector v = (Vector) what;
ArrayPrototype retval = new ArrayPrototype (evaluator.getArrayPrototype (), evaluator);
int l = v.size ();
for (int i=0; i<l; i++)
retval.putProperty (i, processXmlRpcArgument (v.elementAt (i)));
return retval;
}
if (what instanceof Hashtable) {
Hashtable t = (Hashtable) what;
ESObject retval = new ObjectPrototype (evaluator.getObjectPrototype (), evaluator);
for (Enumeration e=t.keys(); e.hasMoreElements(); ) {
String next = (String) e.nextElement ();
retval.putProperty (next, processXmlRpcArgument (t.get (next)), next.hashCode ());
}
return retval;
}
if (what instanceof String)
return new ESString (what.toString ());
if (what instanceof Number)
return new ESNumber (new Double (what.toString ()).doubleValue ());
if (what instanceof Boolean)
return ESBoolean.makeBoolean (((Boolean) what).booleanValue ());
if (what instanceof Date)
return new DatePrototype (evaluator, (Date) what);
return ESLoader.normalizeValue (what, evaluator);
}
/**
* convert a JavaScript Object object to a generic Java object stucture.
*/
public Object processXmlRpcResponse (ESValue what) throws EcmaScriptException {
if (what == null || what instanceof ESNull)
return null;
if (what instanceof ArrayPrototype) {
ArrayPrototype a = (ArrayPrototype) what;
int l = a.size ();
Vector v = new Vector ();
for (int i=0; i<l; i++) {
Object nj = processXmlRpcResponse (a.getProperty (i));
v.addElement (nj);
}
return v;
}
if (what instanceof ObjectPrototype) {
ObjectPrototype o = (ObjectPrototype) what;
Hashtable t = new Hashtable ();
for (Enumeration e=o.getProperties (); e.hasMoreElements (); ) {
String next = (String) e.nextElement ();
// We don't do deep serialization of HopObjects to avoid
// that the whole web site structure is sucked out with one
// object. Instead we return some kind of "proxy" objects
// that only contain the prototype and id of the HopObject property.
Object nj = null;
ESValue esv = o.getProperty (next, next.hashCode ());
if (esv instanceof ESNode) {
INode node = ((ESNode) esv).getNode ();
if (node != null) {
Hashtable nt = new Hashtable ();
nt.put ("id", node.getID());
if (node.getPrototype() != null)
nt.put ("prototype", node.getPrototype ());
nj = nt;
}
} else
nj = processXmlRpcResponse (esv);
if (nj != null) // can't put null as value in hashtable
t.put (next, nj);
}
return t;
}
if (what instanceof ESUndefined || what instanceof ESNull)
return null;
Object jval = what.toJavaObject ();
if (jval instanceof Byte || jval instanceof Short)
jval = new Integer (jval.toString ());
return jval;
}
/** /**
* Return the FESI Evaluator object wrapped by this object. * Return the FESI Evaluator object wrapped by this object.