the XML-RPC code passed its first validation - OK, next: add the "boxcarring"

call system.multicall, and tweak the implementation a bit after seeing the
output "live"
This commit is contained in:
Eric J. Bowersox 2002-01-17 08:33:40 +00:00
parent 394a1863e0
commit 4ee98731e6
6 changed files with 168 additions and 13 deletions

View File

@ -280,6 +280,9 @@
<!-- XML-RPC validation suite --> <!-- XML-RPC validation suite -->
<method name="validator1\.[a-zA-Z]*"><script name="test/validation.js"/></method> <method name="validator1\.[a-zA-Z]*"><script name="test/validation.js"/></method>
<!-- Multicall "boxcar" marshaller (see http://www.xmlrpc.com/discuss/msgReader$1208) -->
<method name="system.multicall"><object class="com.silverwrist.venice.ui.rpc.XmlRpcMulticall"/></method>
<method name="venice:test\.sumDifference"> <method name="venice:test\.sumDifference">
<!-- <object class="com.silverwrist.venice.ui.rpc.XmlRpcTestHandler"/> --> <!-- <object class="com.silverwrist.venice.ui.rpc.XmlRpcTestHandler"/> -->
<script name="test/test1.js"/> <script name="test/test1.js"/>

View File

@ -17,6 +17,8 @@
// Implements the XML-RPC Validation Suite functions as documented by UserLand Software, // Implements the XML-RPC Validation Suite functions as documented by UserLand Software,
// see http://www.xmlrpc.com/validator1Docs // see http://www.xmlrpc.com/validator1Docs
// -- PASSES VALIDATION as of 1/16/2002; 11:31:28 PM
importPackage(java.util); importPackage(java.util);
importPackage(Packages.com.silverwrist.venice.ui.rpc); importPackage(Packages.com.silverwrist.venice.ui.rpc);

View File

@ -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 <http://www.mozilla.org/MPL/>.
*
* 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 <erbo@silcom.com>,
* 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

View File

@ -25,6 +25,7 @@ import org.apache.log4j.*;
import org.w3c.dom.*; import org.w3c.dom.*;
import com.silverwrist.util.*; import com.silverwrist.util.*;
import com.silverwrist.venice.except.*; import com.silverwrist.venice.except.*;
import com.silverwrist.venice.ui.*;
import com.silverwrist.venice.util.XMLLoader; import com.silverwrist.venice.util.XMLLoader;
public class XmlRpcRequest public class XmlRpcRequest
@ -43,15 +44,16 @@ public class XmlRpcRequest
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
*/ */
RequestInput req; // request input system
String method_name; // the method name String method_name; // the method name
List method_params; // the method parameters 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) if (req_doc==null)
throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,"no XML call structure found"); throw new XmlRpcFault(XmlRpcFault.INVALID_REQUEST,"no XML call structure found");
@ -104,6 +106,16 @@ public class XmlRpcRequest
} // end catch } // 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 } // end constructor
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------

View File

@ -447,7 +447,7 @@ public class XmlRpcSerializer
{ {
StringBuffer b = new StringBuffer("<array>\r\n<data>\r\n"); StringBuffer b = new StringBuffer("<array>\r\n<data>\r\n");
while (it.hasNext()) while (it.hasNext())
b.append("<value>").append(this.serialize(it.next())).append("</value>"); b.append("<value>").append(this.serialize(it.next())).append("</value>\r\n");
b.append("</data>\r\n</array>"); b.append("</data>\r\n</array>");
return b.toString(); return b.toString();

View File

@ -111,7 +111,7 @@ public class XmlRpcServlet extends BaseServlet
XmlRpcRequest xreq; XmlRpcRequest xreq;
try try
{ // get the XML-RPC request structure { // get the XML-RPC request structure
xreq = new XmlRpcRequest(req.getRequestDocument()); xreq = new XmlRpcRequest(req,req.getRequestDocument());
} // end try } // end try
catch (XmlRpcFault f) catch (XmlRpcFault f)
@ -120,6 +120,21 @@ public class XmlRpcServlet extends BaseServlet
} // end catch } // 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 // Prepare the parameters map
int i; int i;
HashMap param_repl_map = new HashMap(); HashMap param_repl_map = new HashMap();
@ -168,31 +183,31 @@ public class XmlRpcServlet extends BaseServlet
} // end if } // end if
} while (rescan); } while (rescan); // end do
Object rc;
try try
{ // dispatch the method call { // call the method and translate anything "out of the ordinary" into an XmlRpcFault
Object rc = meth.dispatch(req,xreq,sub_map); rc = meth.dispatch(req,xreq,sub_map);
if (rc==null) if (rc==null)
rc = new XmlRpcFault(XmlRpcFault.APPLICATION_ERROR,"no return value"); rc = new XmlRpcFault(XmlRpcFault.APPLICATION_ERROR,"no return value");
else if (rc instanceof Exception) else if (rc instanceof Exception)
rc = new XmlRpcFault((Exception)rc); rc = new XmlRpcFault((Exception)rc);
else if (!(rc instanceof XmlRpcFault))
rc = new XmlRpcReturnValue(rc);
return rc;
} // end try } // end try
catch (Exception e) catch (Exception e)
{ // if there's an exception, turn it into a "Fault" message { // if there's an exception, turn it into a "Fault" message
return new XmlRpcFault(e); rc = new XmlRpcFault(e);
} // end catch } // end catch
catch (XmlRpcFault f) catch (XmlRpcFault f)
{ // pass faults right on up { // pass faults right on up
return f; rc = f;
} // end catch } // end catch
} // end process return rc;
} // end dispatchMethodCall
} // end class XmlRpcServlet } // end class XmlRpcServlet