diff --git a/etc/ui-config.xml b/etc/ui-config.xml
index 0d0c890..68b943b 100644
--- a/etc/ui-config.xml
+++ b/etc/ui-config.xml
@@ -280,6 +280,9 @@
+
+
+
diff --git a/rpcscripts/test/validation.js b/rpcscripts/test/validation.js
index 8caa261..fa3a242 100644
--- a/rpcscripts/test/validation.js
+++ b/rpcscripts/test/validation.js
@@ -17,6 +17,8 @@
// Implements the XML-RPC Validation Suite functions as documented by UserLand Software,
// see http://www.xmlrpc.com/validator1Docs
+// -- PASSES VALIDATION as of 1/16/2002; 11:31:28 PM
+
importPackage(java.util);
importPackage(Packages.com.silverwrist.venice.ui.rpc);
diff --git a/src/com/silverwrist/venice/ui/rpc/XmlRpcMulticall.java b/src/com/silverwrist/venice/ui/rpc/XmlRpcMulticall.java
new file mode 100644
index 0000000..f919df1
--- /dev/null
+++ b/src/com/silverwrist/venice/ui/rpc/XmlRpcMulticall.java
@@ -0,0 +1,123 @@
+/*
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at .
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
+ * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
+ * language governing rights and limitations under the License.
+ *
+ * The Original Code is the Venice Web Communities System.
+ *
+ * The Initial Developer of the Original Code is Eric J. Bowersox ,
+ * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
+ * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
+ *
+ * Contributor(s):
+ */
+package com.silverwrist.venice.ui.rpc;
+
+import java.util.*;
+import com.silverwrist.venice.ui.*;
+
+public class XmlRpcMulticall implements XmlRpcDispatch
+{
+ /*--------------------------------------------------------------------------------
+ * Constructor
+ *--------------------------------------------------------------------------------
+ */
+
+ public XmlRpcMulticall()
+ { // do nothing
+ } // end constructor
+
+ /*--------------------------------------------------------------------------------
+ * Internal operations
+ *--------------------------------------------------------------------------------
+ */
+
+ private static final XmlRpcRequest parseRequest(RequestInput req, Object obj) throws XmlRpcFault
+ {
+ try
+ { // this object should be a struct with two elements, methodName (string) and params (array).
+ // Parse those out.
+ Map map = (Map)obj;
+ String method_name = (String)(map.get("methodName"));
+ List params = (List)(map.get("params"));
+ if ((method_name==null) || (params==null))
+ throw new XmlRpcFault(XmlRpcFault.INVALID_PARAMS,"missing multicall struct elements");
+ return new XmlRpcRequest(req,method_name,params);
+
+ } // end try
+ catch (ClassCastException cce)
+ { // parameter is not right
+ throw new XmlRpcFault(XmlRpcFault.INVALID_PARAMS,"array parameter type mismatch");
+
+ } // end catch
+
+ } // end parseRequest
+
+ private static final Map faultToStruct(XmlRpcFault f)
+ {
+ Map rc = new TreeMap();
+ rc.put("faultCode",new Integer(f.getFaultCode()));
+ rc.put("faultString",f.getMessage());
+ return rc;
+
+ } // end faultToStruct
+
+ /*--------------------------------------------------------------------------------
+ * Implementations from interface XmlRpcDispatch
+ *--------------------------------------------------------------------------------
+ */
+
+ public Object dispatch(RequestInput req, XmlRpcRequest xreq, Map environment) throws Exception, XmlRpcFault
+ {
+ if (!(xreq.getMethod().equals("system.multicall")))
+ throw new XmlRpcFault(XmlRpcFault.METHOD_NOT_FOUND,"invalid method name: " + xreq.getMethod());
+ if (xreq.getParamCount()!=1)
+ throw new XmlRpcFault(XmlRpcFault.INVALID_PARAMS,"parameter count mismatch");
+
+ List raw_calls;
+ try
+ { // array output
+ raw_calls = (List)(xreq.getParam(0));
+
+ } // end try
+ catch (ClassCastException cce)
+ { // type mismatch
+ throw new XmlRpcFault(XmlRpcFault.INVALID_PARAMS,"parameter type mismatch");
+
+ } // end catch
+
+ if (raw_calls.isEmpty())
+ return Collections.EMPTY_LIST; // no calls here - this is good as a presence check
+
+ // parse out subrequests, call them, and return them
+ ArrayList rc = new ArrayList(raw_calls.size());
+ Iterator it = raw_calls.iterator();
+ while (it.hasNext())
+ { // parse out a request and dispatch it
+ try
+ { // parse the request
+ XmlRpcRequest sub_xreq = parseRequest(req,it.next());
+ Object sub_rc = XmlRpcServlet.dispatchMethodCall(req,sub_xreq);
+ if (sub_rc instanceof XmlRpcFault)
+ sub_rc = faultToStruct((XmlRpcFault)sub_rc);
+ rc.add(sub_rc);
+
+ } // end try
+ catch (XmlRpcFault f)
+ { // save the fault code for the operation
+ rc.add(faultToStruct(f));
+
+ } // end catch
+
+ } // end while
+
+ return rc; // return all the results at once to be serialized
+
+ } // end dispatch
+
+} // end class XmlRpcMulticall
+
diff --git a/src/com/silverwrist/venice/ui/rpc/XmlRpcRequest.java b/src/com/silverwrist/venice/ui/rpc/XmlRpcRequest.java
index 5b7bdc4..a6ce536 100644
--- a/src/com/silverwrist/venice/ui/rpc/XmlRpcRequest.java
+++ b/src/com/silverwrist/venice/ui/rpc/XmlRpcRequest.java
@@ -25,6 +25,7 @@ import org.apache.log4j.*;
import org.w3c.dom.*;
import com.silverwrist.util.*;
import com.silverwrist.venice.except.*;
+import com.silverwrist.venice.ui.*;
import com.silverwrist.venice.util.XMLLoader;
public class XmlRpcRequest
@@ -43,15 +44,16 @@ public class XmlRpcRequest
*--------------------------------------------------------------------------------
*/
+ RequestInput req; // request input system
String method_name; // the method name
List method_params; // the method parameters
/*--------------------------------------------------------------------------------
- * Constructor
+ * Constructors
*--------------------------------------------------------------------------------
*/
- XmlRpcRequest(Document req_doc) throws XmlRpcFault
+ XmlRpcRequest(RequestInput req, Document req_doc) throws XmlRpcFault
{
if (req_doc==null)
throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,"no XML call structure found");
@@ -104,6 +106,16 @@ public class XmlRpcRequest
} // end catch
+ this.req = req; // save reference off
+
+ } // end constructor
+
+ XmlRpcRequest(RequestInput req, String method_name, List method_params)
+ {
+ this.req = req;
+ this.method_name = method_name;
+ this.method_params = method_params;
+
} // end constructor
/*--------------------------------------------------------------------------------
diff --git a/src/com/silverwrist/venice/ui/rpc/XmlRpcSerializer.java b/src/com/silverwrist/venice/ui/rpc/XmlRpcSerializer.java
index b96809a..3ccc926 100644
--- a/src/com/silverwrist/venice/ui/rpc/XmlRpcSerializer.java
+++ b/src/com/silverwrist/venice/ui/rpc/XmlRpcSerializer.java
@@ -447,7 +447,7 @@ public class XmlRpcSerializer
{
StringBuffer b = new StringBuffer("\r\n\r\n");
while (it.hasNext())
- b.append("").append(this.serialize(it.next())).append("");
+ b.append("").append(this.serialize(it.next())).append("\r\n");
b.append("\r\n");
return b.toString();
diff --git a/src/com/silverwrist/venice/ui/rpc/XmlRpcServlet.java b/src/com/silverwrist/venice/ui/rpc/XmlRpcServlet.java
index a5ceae1..b4926f1 100644
--- a/src/com/silverwrist/venice/ui/rpc/XmlRpcServlet.java
+++ b/src/com/silverwrist/venice/ui/rpc/XmlRpcServlet.java
@@ -111,7 +111,7 @@ public class XmlRpcServlet extends BaseServlet
XmlRpcRequest xreq;
try
{ // get the XML-RPC request structure
- xreq = new XmlRpcRequest(req.getRequestDocument());
+ xreq = new XmlRpcRequest(req,req.getRequestDocument());
} // end try
catch (XmlRpcFault f)
@@ -120,6 +120,21 @@ public class XmlRpcServlet extends BaseServlet
} // end catch
+ // dispatch the call and wrap non-fault returns for proper XML formatting
+ Object rc = dispatchMethodCall(req,xreq);
+ if (!(rc instanceof XmlRpcFault))
+ rc = new XmlRpcReturnValue(rc);
+ return rc;
+
+ } // end process
+
+ /*--------------------------------------------------------------------------------
+ * External static operations
+ *--------------------------------------------------------------------------------
+ */
+
+ static Object dispatchMethodCall(RequestInput req, XmlRpcRequest xreq)
+ {
// Prepare the parameters map
int i;
HashMap param_repl_map = new HashMap();
@@ -168,31 +183,31 @@ public class XmlRpcServlet extends BaseServlet
} // end if
- } while (rescan);
+ } while (rescan); // end do
+ Object rc;
try
- { // dispatch the method call
- Object rc = meth.dispatch(req,xreq,sub_map);
+ { // call the method and translate anything "out of the ordinary" into an XmlRpcFault
+ rc = meth.dispatch(req,xreq,sub_map);
if (rc==null)
rc = new XmlRpcFault(XmlRpcFault.APPLICATION_ERROR,"no return value");
else if (rc instanceof Exception)
rc = new XmlRpcFault((Exception)rc);
- else if (!(rc instanceof XmlRpcFault))
- rc = new XmlRpcReturnValue(rc);
- return rc;
} // end try
catch (Exception e)
{ // if there's an exception, turn it into a "Fault" message
- return new XmlRpcFault(e);
+ rc = new XmlRpcFault(e);
} // end catch
catch (XmlRpcFault f)
{ // pass faults right on up
- return f;
+ rc = f;
} // end catch
- } // end process
+ return rc;
+
+ } // end dispatchMethodCall
} // end class XmlRpcServlet