*** empty log message ***

This commit is contained in:
Eric J. Bowersox
2003-05-20 03:25:31 +00:00
commit b80fa05ed1
682 changed files with 85738 additions and 0 deletions
@@ -0,0 +1,136 @@
/*
* 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.dynamo.xmlrpc;
import java.util.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.util.*;
class Capabilities implements XmlRpcDispatcher, XmlRpcTypeNames
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static final String XMLRPC_NAME = "xmlrpc";
private static final String XMLRPC_SPEC = "http://www.xmlrpc.com/spec";
private static final int XMLRPC_VERSION = 1;
private static final String FAULTCODE_NAME = "faults_interop";
private static final String FAULTCODE_SPEC = "http://xmlrpc-epi.sourceforge.net/cpecs/rfc.fault_codes.php";
private static final int FAULTCODE_VERSION = 20010516;
private static final List SUPPORTED_METHODS;
private static final List SIGNATURES;
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private Hashtable m_capas = new Hashtable();
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
Capabilities()
{
insertCapability(XMLRPC_NAME,XMLRPC_SPEC,XMLRPC_VERSION);
insertCapability(FAULTCODE_NAME,FAULTCODE_SPEC,FAULTCODE_VERSION);
} // end constructor
/*--------------------------------------------------------------------------------
* Implementations from interface XmlRpcDispatcher
*--------------------------------------------------------------------------------
*/
public String getSessionIDParamValue(Request r, Application app)
{
return null; // dummy value
} // end getSessionIDParamValue
public Object dispatchXmlRpcCall(Request r, Application app) throws FaultCode
{
if (r.getParameters().size()!=0)
throw new XmlRpcParameterError("system.getCapabilities: wrong parameter count");
return new XmlRpcResult(m_capas);
} // end dispatchXmlRpcCall
public Collection getSupportedMethods(Request r)
{
return SUPPORTED_METHODS;
} // end getSupportedMethods
public List getMethodSignature(Request r, String method) throws FaultCode
{
return SIGNATURES;
} // end getMethodSignature
public String getMethodHelp(Request r, String method) throws FaultCode
{
ResourceBundle b = ResourceBundle.getBundle("com.silverwrist.dynamo.xmlrpc.XmlRpcMessages",
Locale.getDefault());
return b.getString("help.getCaps");
} // end getMethodHelp
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
void insertCapability(String name, String url, int version)
{
HashMap tmp = new HashMap();
tmp.put("specUrl",url);
tmp.put("specVersion",new Integer(version));
m_capas.put(name,Collections.unmodifiableMap(tmp));
} // end insertCapability
ComponentShutdown addCapability(String name, String url, int version)
{
insertCapability(name,url,version);
return new ShutdownHashtableRemove(m_capas,name);
} // end addCapability
/*--------------------------------------------------------------------------------
* Static initializer
*--------------------------------------------------------------------------------
*/
static
{ // Set up the supported methods list.
SUPPORTED_METHODS = Collections.singletonList("system.getCapabilities");
// Set up the signature list.
List l = Collections.singletonList(TYPE_STRUCT);
SIGNATURES = Collections.singletonList(l);
} // end static initializer
} // end class Capabilities
@@ -0,0 +1,172 @@
/*
* 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.dynamo.xmlrpc;
import java.io.*;
import com.silverwrist.util.*;
import com.silverwrist.dynamo.HttpStatusCode;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
public class FaultCode extends Throwable implements SelfRenderable
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
public static final int SYSTEM_FIRST = -32768;
public static final int SYSTEM_LAST = -32000;
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
protected int m_code;
/*--------------------------------------------------------------------------------
* Constructors
*--------------------------------------------------------------------------------
*/
public FaultCode()
{
super();
m_code = 0;
} // end constructor
public FaultCode(int code)
{
super();
m_code = (isSystemFaultCode(code) ? 0 : code);
} // end constructor
public FaultCode(String message)
{
super(message);
m_code = 0;
} // end constructor
public FaultCode(int code, String message)
{
super(message);
m_code = (isSystemFaultCode(code) ? 0 : code);
} // end constructor
public FaultCode(Throwable inner)
{
super(inner.getMessage(),inner);
if (inner instanceof FaultCode)
m_code = ((FaultCode)inner).getCode();
else
m_code = 0;
} // end constructor
public FaultCode(int code, Throwable inner)
{
super(inner.getMessage(),inner);
m_code = (isSystemFaultCode(code) ? 0 : code);
} // end constructor
public FaultCode(String message, Throwable inner)
{
super(message,inner);
if (inner instanceof FaultCode)
m_code = ((FaultCode)inner).getCode();
else
m_code = 0;
} // end constructor
public FaultCode(int code, String message, Throwable inner)
{
super(message,inner);
m_code = (isSystemFaultCode(code) ? 0 : code);
} // end constructor
/*--------------------------------------------------------------------------------
* Implementations from interface SelfRenderable
*--------------------------------------------------------------------------------
*/
public void render(SelfRenderControl control) throws IOException, RenderingException
{
// Create the rendered structure as raw text.
StringBuffer b =
new StringBuffer("<?xml version=\"1.0\"?>\r\n<methodResponse><fault><value><struct>\r\n<member>\r\n"
+ "<name>faultCode</name>\r\n<value><int>");
b.append(m_code);
b.append("</int></value>\r\n</member>\r\n<member>\r\n<name>faultString</name>\r\n<value><string>");
b.append(StringUtils.encodeHTML(getMessage()));
b.append("</string></value>\r\n</member>\r\n</struct></value></fault></methodResponse>\r\n");
// Now render the binary equivalent of this structure.
byte[] data = null;
try
{ // get a complete rendering of this data
data = b.toString().getBytes("UTF-8");
} // end try
catch (UnsupportedEncodingException e)
{ // WTF? shouldn't happen
data = b.toString().getBytes();
} // end catch
// send out the bytes as an XML message body
control.status(HttpStatusCode.S_OK);
BinaryRenderControl bctrl = control.getBinaryRender();
bctrl.setContentType("text/xml; charset=UTF-8");
bctrl.setContentLength(data.length);
OutputStream stm = bctrl.getStream();
stm.write(data);
stm.flush();
} // end render
/*--------------------------------------------------------------------------------
* External static operations
*--------------------------------------------------------------------------------
*/
public static final boolean isSystemFaultCode(int code)
{
return ((code>=SYSTEM_FIRST) && (code<=SYSTEM_LAST));
} // end isSystemFaultCode
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
public int getCode()
{
return m_code;
} // end getCode
} // end class FaultCode
@@ -0,0 +1,234 @@
/*
* 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.dynamo.xmlrpc;
import java.lang.ref.*;
import java.util.*;
import com.silverwrist.dynamo.iface.*;
class IntrospectionDispatcher implements XmlRpcDispatcher, XmlRpcTypeNames
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static final int DISP_LISTMETHODS = 0;
private static final int DISP_METHODSIGNATURE = 1;
private static final int DISP_METHODHELP = 2;
private static final Map DISPATCH_MAP;
private static final List[] SIGNATURES;
private static final String[] HELP_RESOURCES = {
"help.listMeth", "help.methSig", "help.methHelp"
};
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private XmlRpcSubSystem m_subsys;
private SoftReference m_methodlist = null;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
IntrospectionDispatcher(XmlRpcSubSystem subsys)
{
m_subsys = subsys;
} // end constructor
/*--------------------------------------------------------------------------------
* Internal operations
*--------------------------------------------------------------------------------
*/
private static final void test0Param(Request r) throws XmlRpcParameterError
{
if (r.getParameters().size()!=0)
throw new XmlRpcParameterError(r.getQueryString() + ": parameter count mismatch");
} // end test0Param
private static final String test1Param(Request r) throws XmlRpcParameterError
{
if (r.getParameters().size()!=1)
throw new XmlRpcParameterError(r.getQueryString() + ": parameter count mismatch");
Object rc = r.getParameters().get("0");
if (rc instanceof String)
return rc.toString();
throw new XmlRpcParameterError(r.getQueryString() + ": parameter type mismatch");
} // end test1Param
private final List listMethods(Request r)
{
List rc = null;
if (m_methodlist!=null)
rc = (List)(m_methodlist.get());
if (rc==null)
{ // recompute the list of methods
Set disps = m_subsys.getAllDispatchers();
ArrayList output = new ArrayList();
Iterator it = disps.iterator();
while (it.hasNext())
{ // get each dispatcher's available methods and add them to the list
XmlRpcDispatcher xd = (XmlRpcDispatcher)(it.next());
output.addAll(xd.getSupportedMethods(r));
} // end while
// sort the output, keep a reference to it
Collections.sort(output);
rc = Collections.unmodifiableList(output);
m_methodlist = new SoftReference(rc);
} // end if
return rc;
} // end listMethods
private final Object methodSignature(Request r, String method) throws FaultCode
{
// Get the dispatcher for this method.
XmlRpcDispatcher xd = m_subsys.getDispatcher(method);
if (xd==null)
throw new XmlRpcMethodNotFound(method);
// Ask it what the signatures are.
List l = xd.getMethodSignature(r,method);
if ((l==null) || l.isEmpty())
return Boolean.FALSE;
else
return l;
} // end methodSignature
private final String methodHelp(Request r, String method) throws FaultCode
{
// Get the dispatcher for this method.
XmlRpcDispatcher xd = m_subsys.getDispatcher(method);
if (xd==null)
throw new XmlRpcMethodNotFound(method);
// Return the doc string.
return xd.getMethodHelp(r,method);
} // end methodHelp
/*--------------------------------------------------------------------------------
* Implementations from interface XmlRpcDispatcher
*--------------------------------------------------------------------------------
*/
public String getSessionIDParamValue(Request r, Application app)
{
return null;
} // end getSessionIDParamValue
public Object dispatchXmlRpcCall(Request r, Application app) throws Exception, FaultCode
{
Integer index = (Integer)(DISPATCH_MAP.get(r.getQueryString()));
if (index==null)
throw new XmlRpcMethodNotFound(r.getQueryString());
switch (index.intValue())
{
case DISP_LISTMETHODS:
test0Param(r);
return listMethods(r);
case DISP_METHODSIGNATURE:
return methodSignature(r,test1Param(r));
case DISP_METHODHELP:
return methodHelp(r,test1Param(r));
default:
throw new XmlRpcMethodNotFound(r.getQueryString());
} // end switch
} // end dispatchXmlRpcCall
public Collection getSupportedMethods(Request r)
{
return DISPATCH_MAP.keySet();
} // end getSupportedMethods
public List getMethodSignature(Request r, String method) throws FaultCode
{
Integer index = (Integer)(DISPATCH_MAP.get(r.getQueryString()));
if (index==null)
throw new XmlRpcMethodNotFound(r.getQueryString());
return SIGNATURES[index.intValue()];
} // end getMethodSignature
public String getMethodHelp(Request r, String method) throws FaultCode
{
Integer index = (Integer)(DISPATCH_MAP.get(r.getQueryString()));
if (index==null)
throw new XmlRpcMethodNotFound(r.getQueryString());
ResourceBundle b = ResourceBundle.getBundle("com.silverwrist.dynamo.xmlrpc.XmlRpcMessages",
Locale.getDefault());
return b.getString(HELP_RESOURCES[index.intValue()]);
} // end getMethodHelp
/*--------------------------------------------------------------------------------
* Static initializer
*--------------------------------------------------------------------------------
*/
static
{ // Initialize the dispatch map.
HashMap map = new HashMap();
map.put("system.listMethods",new Integer(DISP_LISTMETHODS));
map.put("system.methodSignature",new Integer(DISP_METHODSIGNATURE));
map.put("system.methodHelp",new Integer(DISP_METHODHELP));
DISPATCH_MAP = Collections.unmodifiableMap(map);
// Initialize the signatures list.
List[] arr = new List[3];
ArrayList tmp = new ArrayList(1);
tmp.add(TYPE_ARRAY);
List l = Collections.unmodifiableList(tmp);
arr[DISP_LISTMETHODS] = Collections.singletonList(l);
tmp = new ArrayList(2);
tmp.add(TYPE_ARRAY);
tmp.add(TYPE_STRING);
l = Collections.unmodifiableList(tmp);
arr[DISP_METHODSIGNATURE] = Collections.singletonList(l);
tmp = new ArrayList(2);
tmp.add(TYPE_STRING);
tmp.add(TYPE_STRING);
l = Collections.unmodifiableList(tmp);
arr[DISP_METHODHELP] = Collections.singletonList(l);
SIGNATURES = arr;
} // end static initializer
} // end class IntrospectionDispatcher
@@ -0,0 +1,190 @@
/*
* 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.dynamo.xmlrpc;
import java.util.*;
import com.silverwrist.dynamo.iface.*;
class MultiCallDispatcher implements XmlRpcDispatcher, XmlRpcTypeNames
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static final List SUPPORTED_METHODS;
private static final List SIGNATURES;
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private XmlRpcSubSystem m_subsystem;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
MultiCallDispatcher(XmlRpcSubSystem subsystem)
{
m_subsystem = subsystem;
} // end constructor
/*--------------------------------------------------------------------------------
* Internal operations
*--------------------------------------------------------------------------------
*/
private static final Map translateFaultCode(FaultCode fc)
{
HashMap rc = new HashMap();
rc.put("faultCode",new Integer(fc.getCode()));
rc.put("faultString",fc.getMessage());
return Collections.unmodifiableMap(rc);
} // end translateFaultCode
private final Object callViaStructure(Request r, Application app, Object struc) throws FaultCode
{
// Validate that this is a structure of the right type, and get the method name and the
// parameters.
if (!(struc instanceof Map))
throw new XmlRpcParameterError("system.multicall: expected struct");
Map my_map = (Map)struc;
Object foo = my_map.get("methodName");
if (foo==null)
throw new XmlRpcParameterError("system.multicall: missing methodName");
if (!(foo instanceof String))
throw new XmlRpcParameterError("system.multicall: methodName not string");
String method_name = (String)foo;
foo = my_map.get("params");
if (foo==null)
throw new XmlRpcParameterError("system.multicall: missing params");
if (!(foo instanceof List))
throw new XmlRpcParameterError("system.multicall: params not array");
List params = (List)foo;
// Build our "nested" request and dispatch it.
MultiCallRequest new_r = new MultiCallRequest(r,method_name,params);
try
{ // run this through the dispatcher!
return m_subsystem.dispatch(new_r,app);
} // end try
catch (Exception e)
{ // translate exception to FaultCode before we return
return m_subsystem.translateException(new_r,e);
} // end catch
} // end callViaStructure
/*--------------------------------------------------------------------------------
* Implementations from interface XmlRpcDispatcher
*--------------------------------------------------------------------------------
*/
public String getSessionIDParamValue(Request r, Application app)
{
return null; // dummy value
} // end getSessionIDParamValue
public Object dispatchXmlRpcCall(Request r, Application app) throws FaultCode
{
Map pm = r.getParameters();
if (pm.size()!=1)
throw new XmlRpcParameterError("system.multicall: wrong parameter count");
Object parm = pm.get("0");
if (!(parm instanceof List))
throw new XmlRpcParameterError("system.multicall: parameter not array");
List call_strucs = (List)parm;
List return_strucs = new ArrayList(call_strucs.size());
Iterator it = call_strucs.iterator();
while (it.hasNext())
{ // get each call structure in turn and make sure it's OK
Object call = it.next();
Object rc = null;
try
{ // execute this call!
rc = callViaStructure(r,app,call);
if (rc instanceof FaultCode)
rc = translateFaultCode((FaultCode)rc);
else // encapsulate in a 1-element array
rc = Collections.singletonList(rc);
} // end try
catch (FaultCode fc)
{ // translate a fault code if it gets thrown
rc = translateFaultCode(fc);
} // end catch
return_strucs.add(rc); // add return value to list
} // end while
return new XmlRpcResult(return_strucs); // return list of return structures
} // end dispatchXmlRpcCall
public Collection getSupportedMethods(Request r)
{
return SUPPORTED_METHODS;
} // end getSupportedMethods
public List getMethodSignature(Request r, String method)
{
return SIGNATURES;
} // end getMethodSignatures
public String getMethodHelp(Request r, String method)
{
ResourceBundle b = ResourceBundle.getBundle("com.silverwrist.dynamo.xmlrpc.XmlRpcMessages",
Locale.getDefault());
return b.getString("help.multicall");
} // end getMethodHelp
/*--------------------------------------------------------------------------------
* Static initializer
*--------------------------------------------------------------------------------
*/
static
{ // Initialize the supported methods list.
SUPPORTED_METHODS = Collections.singletonList("system.multicall");
// Initialize the signatures list.
ArrayList tmp = new ArrayList(2);
tmp.add(TYPE_ARRAY);
tmp.add(TYPE_ARRAY);
List l = Collections.unmodifiableList(tmp);
tmp = new ArrayList(1);
tmp.add(l);
SIGNATURES = Collections.unmodifiableList(tmp);
} // end static initializer
} // end class MultiCallDispatcher
@@ -0,0 +1,72 @@
/*
* 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.dynamo.xmlrpc;
import java.util.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.util.*;
class MultiCallRequest extends FilterRequest
{
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private String m_method;
private Map m_params;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
MultiCallRequest(Request inner, String method, List params)
{
super(inner);
m_method = method;
HashMap tmp = new HashMap();
Iterator it = params.iterator();
int ndx = 0;
while (it.hasNext())
tmp.put(String.valueOf(ndx++),it.next());
if (tmp.isEmpty())
m_params = Collections.EMPTY_MAP;
else
m_params = Collections.unmodifiableMap(tmp);
} // end constructor
/*--------------------------------------------------------------------------------
* Overrides from class FilterRequest
*--------------------------------------------------------------------------------
*/
public String getQueryString()
{
return m_method;
} // end getQueryString
public Map getParameters()
{
return m_params;
} // end getParameters
} // end class MultiCallRequest
@@ -0,0 +1,97 @@
/*
* 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.dynamo.xmlrpc;
import java.util.regex.*;
import com.silverwrist.dynamo.except.*;
class RegisteredDispatcher
{
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private Pattern m_pattern;
private String m_expr;
private XmlRpcDispatcher m_dispatcher;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
RegisteredDispatcher(String expr, XmlRpcDispatcher dispatcher) throws ConfigException
{
try
{ // compile the pattern and save the dispatcher
if (!(expr.startsWith("^")))
expr = "^" + expr;
m_pattern = Pattern.compile(expr);
m_expr = expr;
m_dispatcher = dispatcher;
} // end try
catch (PatternSyntaxException e)
{ // convert this to a ConfigException
ConfigException ce = new ConfigException(RegisteredDispatcher.class,"XmlRpcMessages","pattern.error",e);
ce.setParameter(0,expr);
throw ce;
} // end catch
} // end constructor
/*--------------------------------------------------------------------------------
* Overrides from class Object
*--------------------------------------------------------------------------------
*/
public boolean equals(Object o)
{
if ((o==null) || !(o instanceof RegisteredDispatcher))
return false;
RegisteredDispatcher other = (RegisteredDispatcher)o;
return (m_expr.equals(other.m_expr) && (m_dispatcher==other.m_dispatcher));
} // end equals
public int hashCode()
{
return m_expr.hashCode() ^ System.identityHashCode(m_dispatcher);
} // end hashCode
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
boolean match(String method_name)
{
return m_pattern.matcher(method_name).matches();
} // end match
XmlRpcDispatcher getDispatcher()
{
return m_dispatcher;
} // end getDispatcher
} // end class RegisteredDispatcher
@@ -0,0 +1,79 @@
/*
* 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.dynamo.xmlrpc;
class RegisteredFaultMapper
{
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private Class m_class;
private XmlRpcFaultMapper m_fmap;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
RegisteredFaultMapper(Class klass, XmlRpcFaultMapper fmap)
{
m_class = klass;
m_fmap = fmap;
} // end constructor
/*--------------------------------------------------------------------------------
* Overrides from class Object
*--------------------------------------------------------------------------------
*/
public boolean equals(Object o)
{
if ((o==null) || !(o instanceof RegisteredFaultMapper))
return false;
RegisteredFaultMapper other = (RegisteredFaultMapper)o;
return ((m_class==other.m_class) && (m_fmap==other.m_fmap));
} // end equals
public int hashCode()
{
return m_class.hashCode() ^ System.identityHashCode(m_fmap);
} // end hashCode
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
boolean match(Class klass)
{
return (m_class==klass);
} // end match
XmlRpcFaultMapper getFaultMapper()
{
return m_fmap;
} // end getFaultMapper
} // end class RegisteredFaultMapper
@@ -0,0 +1,68 @@
/*
* 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.dynamo.xmlrpc;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.util.*;
class ReplaceSessionRequest extends FilterRequest
{
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private DefaultSessionInfoProvider m_prov;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
ReplaceSessionRequest(Request inner, SessionInfo session)
{
super(inner);
m_prov = new DefaultSessionInfoProvider(session);
} // end constructor
/*--------------------------------------------------------------------------------
* Overrides from class FilterRequest
*--------------------------------------------------------------------------------
*/
/**
* Queries this object for a specified service.
*
* @param klass The class of the object that should be returned as a service.
* @return A service object. The service object is guaranteed to be of the class
* specified by <CODE>klass</CODE>; that is, if <CODE>queryService(klass)</CODE>
* yields some object <CODE>x</CODE>, then the expression <CODE>klass.isInstance(x)</CODE>
* is true.
* @exception com.silverwrist.dynamo.except.NoSuchServiceException If no service is available in
* the specified class.
*/
public Object queryService(Class klass)
{
if (klass==SessionInfoProvider.class)
return m_prov;
return super.queryService(klass);
} // end queryService
} // end class ReplaceSessionRequest
@@ -0,0 +1,171 @@
/*
* 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.dynamo.xmlrpc;
import java.io.*;
import java.util.*;
import org.w3c.dom.*;
import com.silverwrist.util.*;
import com.silverwrist.util.xml.*;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
public class ScriptDispatcher implements ComponentInitialize, XmlRpcDispatcher
{
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private String m_script_name;
private String m_session_param = null;
private Hashtable m_metadata = new Hashtable();
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
ScriptDispatcher()
{ // do nothing
} // end constructor
/*--------------------------------------------------------------------------------
* Internal operations
*--------------------------------------------------------------------------------
*/
private final void loadMetadataList(List l) throws ConfigException
{
Iterator it = l.iterator();
while (it.hasNext())
{ // create metadata elements
Element elt = (Element)(it.next());
XMLMetadata md = new XMLMetadata(elt);
m_metadata.put(md.getMethodName(),md);
} // end while
} // end loadMetadataList
/*--------------------------------------------------------------------------------
* Implementations from interface ComponentInitialize
*--------------------------------------------------------------------------------
*/
public void initialize(Element config_root, ServiceProvider services) throws ConfigException
{
XMLLoader loader = XMLLoader.get();
try
{ // get the script name
DOMElementHelper config_root_h = new DOMElementHelper(config_root);
m_script_name = loader.getSubElementText(config_root_h,"script");
// get the session parameter
Element elt = config_root_h.getSubElement("session");
if (elt!=null)
m_session_param = loader.getAttribute(elt,"param");
// load a metadata file if it's present
String md_file = config_root_h.getSubElementText("metadata-file");
if (md_file!=null)
{ // try and load the metadata file
InputStream stm = null;
try
{ // load the resource and parse it into XML
ResourceProvider rprov = (ResourceProvider)(services.queryService(ResourceProvider.class));
stm = rprov.getResource(md_file);
Document doc = loader.load(stm,false);
Element md_root = loader.getRootElement(doc,"metadata-file");
loadMetadataList(loader.getMatchingSubElements(md_root,"metadata"));
} // end try
catch (NoSuchResourceException e)
{ // just ignore the file
} // end catch
catch (IOException e)
{ // just ignore the file
} // end catch
finally
{ // shut down stream
IOUtils.shutdown(stm);
} // end finally
} // end if (metadata file specified)
// load direct metadata if it's present
loadMetadataList(loader.getMatchingSubElements(config_root,"metadata"));
} // end try
catch (XMLLoadException e)
{ // translate to ConfigException
throw new ConfigException(e);
} // end catch
} // end initialize
/*--------------------------------------------------------------------------------
* Implementations from interface XmlRpcDispatcher
*--------------------------------------------------------------------------------
*/
public String getSessionIDParamValue(Request r, Application app)
{
if (m_session_param==null)
return null;
Object o = r.getParameters().get(m_session_param);
return ((o==null) ? null : o.toString());
} // end getSessionIDParamValue
public Object dispatchXmlRpcCall(Request r, Application app) throws Exception, FaultCode
{
ScriptExecute exec = (ScriptExecute)(r.queryService(ScriptExecute.class));
return exec.executeScript(r,m_script_name);
} // end dispatchXmlRpcCall
public Collection getSupportedMethods(Request r)
{
return Collections.unmodifiableSet(m_metadata.keySet());
} // end getSupportedMethods
public List getMethodSignature(Request r, String method) throws FaultCode
{
XMLMetadata md = (XMLMetadata)(m_metadata.get(method));
if (md!=null)
return md.getSignatures();
else
return null;
} // end getMethodSignature
public String getMethodHelp(Request r, String method) throws FaultCode
{
XMLMetadata md = (XMLMetadata)(m_metadata.get(method));
if (md!=null)
return md.getDocumentation();
else
return "";
} // end getMethodHelp
} // end class ScriptDispatcher
@@ -0,0 +1,98 @@
/*
* 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.dynamo.xmlrpc;
class SystemFaultCode extends FaultCode
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
public static final int PARSE_ERROR = -32700;
public static final int BAD_ENCODING = -32701;
public static final int INVALID_CHARACTER = -32702;
public static final int INVALID_REQUEST = -32600;
public static final int METHOD_NOT_FOUND = -32601;
public static final int INVALID_PARAMS = -32602;
public static final int INTERNAL_ERROR = -32603;
public static final int APPLICATION_ERROR = -32500;
public static final int SERVER_ERROR = -32400;
public static final int TRANSPORT_ERROR = -32300;
public static final int IMPL_ERROR_FIRST = -32099;
public static final int IMPL_ERROR_LAST = -32000;
/*--------------------------------------------------------------------------------
* Constructors
*--------------------------------------------------------------------------------
*/
SystemFaultCode()
{
super();
} // end constructor
SystemFaultCode(int code)
{
super();
m_code = code;
} // end constructor
SystemFaultCode(String message)
{
super(message);
} // end constructor
SystemFaultCode(int code, String message)
{
super(message);
m_code = code;
} // end constructor
SystemFaultCode(Throwable inner)
{
super(inner);
} // end constructor
SystemFaultCode(int code, Throwable inner)
{
super(inner);
m_code = code;
} // end constructor
SystemFaultCode(String message, Throwable inner)
{
super(message,inner);
} // end constructor
SystemFaultCode(int code, String message, Throwable inner)
{
super(message,inner);
m_code = code;
} // end constructor
} // end class SystemFaultCode
@@ -0,0 +1,411 @@
/*
* 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.dynamo.xmlrpc;
import java.util.*;
import org.apache.commons.lang.CharSetUtils;
import com.silverwrist.util.*;
import com.silverwrist.dynamo.iface.*;
/**
* Implements the functions called by the UserLand Software XML-RPC Validator, which act as a test
* for the XML-RPC protocol stack.
*
* @author Eric J. Bowersox &lt;erbo@silcom.com&gt;
* @version X
*/
public class Validator1Suite implements XmlRpcDispatcher, XmlRpcTypeNames
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static final int DISP_ARRAYOFSTRUCTS = 0;
private static final int DISP_COUNTTHEENTITIES = 1;
private static final int DISP_EASYSTRUCT = 2;
private static final int DISP_ECHOSTRUCT = 3;
private static final int DISP_MANYTYPES = 4;
private static final int DISP_MODERATESIZEARRAY = 5;
private static final int DISP_NESTEDSTRUCT = 6;
private static final int DISP_SIMPLESTRUCTRETURN = 7;
private static final Map DISPATCH_MAP;
private static final List[] SIGNATURES;
private static final String[] HELP_RESOURCES = {
"help.v1.arrayOf", "help.v1.countEnt", "help.v1.ezStruct", "help.v1.echoStr",
"help.v1.manyType", "help.v1.mSAC", "help.v1.nestStr", "help.v1.simple"
};
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public Validator1Suite()
{ // do nothing
} // end constructor
/*--------------------------------------------------------------------------------
* Internal operations
*--------------------------------------------------------------------------------
*/
/**
* <CODE>validator1.arrayOfStructsTest(array) returns integer</CODE><P>
* The parameter is an array of structs containing at least three elements, named
* "moe", "larry", and "curly", all of which are integers. Function must add up all
* the "curly" elements and return the sum.
*
* @param r The {@link com.silverwrist.dynamo.iface.Request} object containing the
* parameters.
* @return The return value from the method call.
* @exception com.silverwrist.dynamo.xmlrpc.FaultCode If there is an error in the parameters.
*/
private Integer arrayOfStructsTest(Request r) throws FaultCode
{
Map pm = r.getParameters();
if (pm.size()!=1)
throw new XmlRpcParameterError("validator1.arrayOfStructsTest: wrong parameter count");
Object foo = pm.get("0");
if (!(foo instanceof List))
throw new XmlRpcParameterError("validator1.arrayOfStructsTest: array expected");
int accum = 0;
Iterator it = ((List)foo).iterator();
while (it.hasNext())
{ // cycle through the list of structs
foo = it.next();
if (!(foo instanceof Map))
throw new XmlRpcParameterError("validator1.arrayOfStructsTest: struct expected");
Map struc = (Map)foo;
foo = struc.get("curly");
if ((foo!=null) && (foo instanceof Integer))
accum += ((Integer)foo).intValue();
} // end while
return new Integer(accum);
} // end arrayOfStructsTest
/**
* <CODE>validator1.countTheEntities(string) returns struct</CODE><P>
*/
private Map countTheEntities(Request r) throws FaultCode
{
Map pm = r.getParameters();
if (pm.size()!=1)
throw new XmlRpcParameterError("validator1.countTheEntities: wrong parameter count");
Object foo = pm.get("0");
if (!(foo instanceof String))
throw new XmlRpcParameterError("validator1.countTheEntities: string expected");
String s = (String)foo;
// Create the output value.
HashMap rc = new HashMap();
rc.put("ctLeftAngleBrackets",new Integer(CharSetUtils.count(s,"<")));
rc.put("ctRightAngleBrackets",new Integer(CharSetUtils.count(s,">")));
rc.put("ctAmpersands",new Integer(CharSetUtils.count(s,"&")));
rc.put("ctApostrophes",new Integer(CharSetUtils.count(s,"'")));
rc.put("ctQuotes",new Integer(CharSetUtils.count(s,"\"")));
return rc;
} // end countTheEntities
private Integer easyStructTest(Request r) throws FaultCode
{
Map pm = r.getParameters();
if (pm.size()!=1)
throw new XmlRpcParameterError("validator1.easyStructTest: wrong parameter count");
Object foo = pm.get("0");
if (!(foo instanceof Map))
throw new XmlRpcParameterError("validator1.easyStructTest: struct expected");
Map struc = (Map)foo;
int sum = 0;
foo = struc.get("moe");
if ((foo!=null) && (foo instanceof Integer))
sum += ((Integer)foo).intValue();
foo = struc.get("larry");
if ((foo!=null) && (foo instanceof Integer))
sum += ((Integer)foo).intValue();
foo = struc.get("curly");
if ((foo!=null) && (foo instanceof Integer))
sum += ((Integer)foo).intValue();
return new Integer(sum);
} // end easyStructTest
private Map echoStructTest(Request r) throws FaultCode
{
Map pm = r.getParameters();
if (pm.size()!=1)
throw new XmlRpcParameterError("validator1.echoStructTest: wrong parameter count");
Object foo = pm.get("0");
if (!(foo instanceof Map))
throw new XmlRpcParameterError("validator1.echoStructTest: struct expected");
return (Map)foo;
} // end echoStructTest
private List manyTypesTest(Request r) throws FaultCode
{
Map pm = r.getParameters();
if (pm.size()!=6)
throw new XmlRpcParameterError("validator1.manyTypesTest: wrong parameter count");
if (!(pm.get("0") instanceof Integer))
throw new XmlRpcParameterError("validator1.manyTypesTest: integer expected");
if (!(pm.get("1") instanceof Boolean))
throw new XmlRpcParameterError("validator1.manyTypesTest: boolean expected");
if (!(pm.get("2") instanceof String))
throw new XmlRpcParameterError("validator1.manyTypesTest: string expected");
if (!(pm.get("3") instanceof Double))
throw new XmlRpcParameterError("validator1.manyTypesTest: double expected");
if (!(pm.get("4") instanceof Date))
throw new XmlRpcParameterError("validator1.manyTypesTest: date expected");
if (!(pm.get("5") instanceof byte[]))
throw new XmlRpcParameterError("validator1.manyTypesTest: base64 expected");
ArrayList rc = new ArrayList(6);
for (int i=0; i<6; i++)
rc.add(pm.get(String.valueOf(i)));
return rc;
} // end manyTypesTest
private String moderateSizeArrayCheck(Request r) throws FaultCode
{
Map pm = r.getParameters();
if (pm.size()!=1)
throw new XmlRpcParameterError("validator1.moderateSizeArrayCheck: wrong parameter count");
Object foo = pm.get("0");
if (!(foo instanceof List))
throw new XmlRpcParameterError("validator1.moderateSizeArrayCheck: array expected");
List arr = (List)foo;
StringBuffer rc = new StringBuffer(arr.get(0).toString());
rc.append(arr.get(arr.size()-1));
return rc.toString();
} // end moderateSizeArrayCheck
private Integer nestedStructTest(Request r) throws FaultCode
{
Map pm = r.getParameters();
if (pm.size()!=1)
throw new XmlRpcParameterError("validator1.nestedStructTest: wrong parameter count");
Object foo = pm.get("0");
if (!(foo instanceof Map))
throw new XmlRpcParameterError("validator1.nestedStructTest: struct expected");
Map current = (Map)foo;
// Navigate down through the structure until we find the right map.
foo = current.get("2000");
if ((foo==null) || !(foo instanceof Map))
throw new XmlRpcParameterError("validator1.nestedStructTest: struct expected");
current = (Map)foo;
foo = current.get("04");
if ((foo==null) || !(foo instanceof Map))
throw new XmlRpcParameterError("validator1.nestedStructTest: struct expected");
current = (Map)foo;
foo = current.get("01");
if ((foo==null) || !(foo instanceof Map))
throw new XmlRpcParameterError("validator1.nestedStructTest: struct expected");
current = (Map)foo;
// Get the three integer fields, add them and return the result.
int sum = 0;
foo = current.get("moe");
if ((foo!=null) && (foo instanceof Integer))
sum += ((Integer)foo).intValue();
foo = current.get("larry");
if ((foo!=null) && (foo instanceof Integer))
sum += ((Integer)foo).intValue();
foo = current.get("curly");
if ((foo!=null) && (foo instanceof Integer))
sum += ((Integer)foo).intValue();
return new Integer(sum);
} // end nestedStructTest
private Map simpleStructReturnTest(Request r) throws FaultCode
{
Map pm = r.getParameters();
if (pm.size()!=1)
throw new XmlRpcParameterError("validator1.simpleStructReturnTest: wrong parameter count");
Object foo = pm.get("0");
if (!(foo instanceof Integer))
throw new XmlRpcParameterError("validator1.simpleStructReturnTest: integer expected");
int base_val = ((Integer)foo).intValue();
// create the return structure
HashMap rc = new HashMap();
rc.put("times10",new Integer(base_val * 10));
rc.put("times100",new Integer(base_val * 100));
rc.put("times1000",new Integer(base_val * 1000));
return rc;
} // end simpleStructReturnTest
/*--------------------------------------------------------------------------------
* Implementations from interface XmlRpcDispatcher
*--------------------------------------------------------------------------------
*/
public String getSessionIDParamValue(Request r, Application app)
{
return null;
} // end getSessionIDParamValue
public Object dispatchXmlRpcCall(Request r, Application app) throws FaultCode
{
Integer disp = (Integer)(DISPATCH_MAP.get(r.getQueryString()));
if (disp==null)
throw new XmlRpcMethodNotFound(r.getQueryString());
switch (disp.intValue())
{
case DISP_ARRAYOFSTRUCTS:
return arrayOfStructsTest(r);
case DISP_COUNTTHEENTITIES:
return countTheEntities(r);
case DISP_EASYSTRUCT:
return easyStructTest(r);
case DISP_ECHOSTRUCT:
return echoStructTest(r);
case DISP_MANYTYPES:
return manyTypesTest(r);
case DISP_MODERATESIZEARRAY:
return moderateSizeArrayCheck(r);
case DISP_NESTEDSTRUCT:
return nestedStructTest(r);
case DISP_SIMPLESTRUCTRETURN:
return simpleStructReturnTest(r);
default:
throw new XmlRpcMethodNotFound(r.getQueryString());
} // end switch
} // end dispatchXmlRpcCall
public Collection getSupportedMethods(Request r)
{
return DISPATCH_MAP.keySet();
} // end getSupportedMethods
public List getMethodSignature(Request r, String method) throws FaultCode
{
Integer disp = (Integer)(DISPATCH_MAP.get(method));
if (disp==null)
throw new XmlRpcMethodNotFound(method);
return SIGNATURES[disp.intValue()];
} // end getMethodSignature
public String getMethodHelp(Request r, String method) throws FaultCode
{
Integer disp = (Integer)(DISPATCH_MAP.get(method));
if (disp==null)
throw new XmlRpcMethodNotFound(method);
ResourceBundle b = ResourceBundle.getBundle("com.silverwrist.dynamo.xmlrpc.XmlRpcMessages",
Locale.getDefault());
return b.getString(HELP_RESOURCES[disp.intValue()]);
} // end getMethodHelp
/*--------------------------------------------------------------------------------
* Static initializer
*--------------------------------------------------------------------------------
*/
static
{ // Create the dispatch map.
HashMap mtmp = new HashMap();
mtmp.put("validator1.arrayOfStructsTest",new Integer(DISP_ARRAYOFSTRUCTS));
mtmp.put("validator1.countTheEntities",new Integer(DISP_COUNTTHEENTITIES));
mtmp.put("validator1.easyStructTest",new Integer(DISP_EASYSTRUCT));
mtmp.put("validator1.echoStructTest",new Integer(DISP_ECHOSTRUCT));
mtmp.put("validator1.manyTypesTest",new Integer(DISP_MANYTYPES));
mtmp.put("validator1.moderateSizeArrayCheck",new Integer(DISP_MODERATESIZEARRAY));
mtmp.put("validator1.nestedStructTest",new Integer(DISP_NESTEDSTRUCT));
mtmp.put("validator1.simpleStructReturnTest",new Integer(DISP_SIMPLESTRUCTRETURN));
DISPATCH_MAP = Collections.unmodifiableMap(mtmp);
// Create the signatures.
List[] arr = new List[8];
ArrayList tmp = new ArrayList(2);
tmp.add(TYPE_INT);
tmp.add(TYPE_ARRAY);
List l = Collections.unmodifiableList(tmp);
arr[DISP_ARRAYOFSTRUCTS] = Collections.singletonList(l);
tmp = new ArrayList(2);
tmp.add(TYPE_STRUCT);
tmp.add(TYPE_STRING);
l = Collections.unmodifiableList(tmp);
arr[DISP_COUNTTHEENTITIES] = Collections.singletonList(l);
tmp = new ArrayList(2);
tmp.add(TYPE_INT);
tmp.add(TYPE_STRUCT);
l = Collections.unmodifiableList(tmp);
arr[DISP_EASYSTRUCT] = Collections.singletonList(l);
tmp = new ArrayList(2);
tmp.add(TYPE_STRUCT);
tmp.add(TYPE_STRUCT);
l = Collections.unmodifiableList(tmp);
arr[DISP_ECHOSTRUCT] = Collections.singletonList(l);
tmp = new ArrayList(7);
tmp.add(TYPE_ARRAY);
tmp.add(TYPE_INT);
tmp.add(TYPE_BOOLEAN);
tmp.add(TYPE_STRING);
tmp.add(TYPE_DOUBLE);
tmp.add(TYPE_DATETIME);
tmp.add(TYPE_BASE64);
l = Collections.unmodifiableList(tmp);
arr[DISP_MANYTYPES] = Collections.singletonList(l);
tmp = new ArrayList(2);
tmp.add(TYPE_STRING);
tmp.add(TYPE_ARRAY);
l = Collections.unmodifiableList(tmp);
arr[DISP_MODERATESIZEARRAY] = Collections.singletonList(l);
tmp = new ArrayList(2);
tmp.add(TYPE_INT);
tmp.add(TYPE_STRUCT);
l = Collections.unmodifiableList(tmp);
arr[DISP_NESTEDSTRUCT] = Collections.singletonList(l);
tmp = new ArrayList(2);
tmp.add(TYPE_STRUCT);
tmp.add(TYPE_INT);
l = Collections.unmodifiableList(tmp);
arr[DISP_SIMPLESTRUCTRETURN] = Collections.singletonList(l);
SIGNATURES = arr;
} // end static
} // end class Validator1Suite
@@ -0,0 +1,174 @@
/*
* 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.dynamo.xmlrpc;
import java.util.*;
import org.w3c.dom.*;
import com.silverwrist.util.xml.*;
import com.silverwrist.dynamo.except.*;
class XMLMetadata implements XmlRpcTypeNames
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static final Set VALID_TYPES;
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private String m_method_name;
private List m_signatures;
private String m_docs;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
XMLMetadata(Element md_root) throws ConfigException
{
XMLLoader loader = XMLLoader.get();
try
{ // get the method name
m_method_name = loader.getAttribute(md_root,"method");
// look for method signatures
ArrayList sigs = new ArrayList();
List l_sigs = loader.getMatchingSubElements(md_root,"signature");
Iterator it = l_sigs.iterator();
while (it.hasNext())
{ // get each signature
Element sig_elt = (Element)(it.next());
// get the return type
ArrayList sdata = new ArrayList();
String s = loader.getSubElementText(sig_elt,"return").trim();
verifyType(s);
sdata.add(s);
// get all parameters
List l_parms = loader.getMatchingSubElements(sig_elt,"param");
Iterator it2 = l_parms.iterator();
while (it2.hasNext())
{ // get each parameter in turn
Element elt = (Element)(it2.next());
s = loader.getText(elt).trim();
verifyType(s);
sdata.add(s);
} // end while
// add signature to the list
sdata.trimToSize();
sigs.add(Collections.unmodifiableList(sdata));
} // end while
if (sigs.isEmpty())
{ // no signatures - throw an exception
ConfigException ce = new ConfigException(XMLMetadata.class,"XmlRpcMessages","md.noSigs");
ce.setParameter(0,m_method_name);
throw ce;
} // end if
// save the signatures
sigs.trimToSize();
m_signatures = Collections.unmodifiableList(sigs);
// load the documentation
DOMElementHelper h = new DOMElementHelper(md_root);
m_docs = h.getSubElementText("doc");
if (m_docs==null)
m_docs = "";
} // end try
catch (XMLLoadException e)
{ // translate into ConfigException
throw new ConfigException(e);
} // end catch
} // end constructor
/*--------------------------------------------------------------------------------
* Internal operations
*--------------------------------------------------------------------------------
*/
private static final void verifyType(String typename) throws ConfigException
{
if (!(VALID_TYPES.contains(typename)))
{ // type value is not valid
ConfigException ce = new ConfigException(XMLMetadata.class,"XmlRpcMessages","md.badType");
ce.setParameter(0,typename);
throw ce;
} // end if
} // end verifyType
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
String getMethodName()
{
return m_method_name;
} // end getMethodName
List getSignatures()
{
return m_signatures;
} // end getSignatures
String getDocumentation()
{
return m_docs;
} // end getDocumentation
/*--------------------------------------------------------------------------------
* Static initializer
*--------------------------------------------------------------------------------
*/
static
{ // Initialize the valid type set.
HashSet tmp = new HashSet();
tmp.add(TYPE_INT);
tmp.add(TYPE_BOOLEAN);
tmp.add(TYPE_STRING);
tmp.add(TYPE_DOUBLE);
tmp.add(TYPE_DATETIME);
tmp.add(TYPE_BASE64);
tmp.add(TYPE_STRUCT);
tmp.add(TYPE_ARRAY);
VALID_TYPES = Collections.unmodifiableSet(tmp);
} // end static initializer
} // end class XMLMetadata
@@ -0,0 +1,31 @@
/*
* 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.dynamo.xmlrpc;
import com.silverwrist.dynamo.except.ConfigException;
import com.silverwrist.dynamo.iface.ComponentShutdown;
public interface XmlRpcConfiguration
{
public ComponentShutdown addDispatcher(String method, XmlRpcDispatcher disp) throws ConfigException;
public ComponentShutdown addFaultMapper(Class klass, XmlRpcFaultMapper fmap) throws ConfigException;
public ComponentShutdown addCapability(String name, String url, int version);
} // end interface XmlRpcConfiguration
@@ -0,0 +1,27 @@
/*
* 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.dynamo.xmlrpc;
import com.silverwrist.dynamo.iface.Request;
import com.silverwrist.dynamo.iface.SessionInfo;
public interface XmlRpcCreateSession
{
public SessionInfo createNewSession(Request r);
} // end interface XmlRpcCreateSession
@@ -0,0 +1,37 @@
/*
* 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.dynamo.xmlrpc;
import java.util.Collection;
import java.util.List;
import com.silverwrist.dynamo.iface.Application;
import com.silverwrist.dynamo.iface.Request;
public interface XmlRpcDispatcher
{
public String getSessionIDParamValue(Request r, Application app);
public Object dispatchXmlRpcCall(Request r, Application app) throws Exception, FaultCode;
public Collection getSupportedMethods(Request r);
public List getMethodSignature(Request r, String method) throws FaultCode;
public String getMethodHelp(Request r, String method) throws FaultCode;
} // end interface XmlRpcDispatcher
@@ -0,0 +1,26 @@
/*
* 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.dynamo.xmlrpc;
import com.silverwrist.dynamo.iface.Request;
public interface XmlRpcFaultMapper
{
public int getXmlRpcFaultCodeForException(Request r, Throwable t);
} // end interface XmlRpcFaultMapper
@@ -0,0 +1,81 @@
# 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):
# ---------------------------------------------------------------------------------
# This file has been localized for the en_US locale
pattern.error=The regular expression pattern "{0}" is not valid.
xdisp.notXD=The class {0} is not a valid XML-RPC dispatcher class.
xdisp.classNotFound=The object class {0} was not found.
xdisp.createError=Unable to create new object of class {0}.
xfmap.noExceptClass=The exception class {0} was not found.
xfmap.badExceptClass=The class {0} is not a valid exception class.
xfmap.notXFM=The class {0} is not a valid XML-RPC fault mapper class.
xfmap.classNotFound=The object class {0} was not found.
xfmap.createError=Unable to create new object of class {0}.
md.badType=Invalid data type specifier "{0}".
md.noSigs=No type signatures specified in metadata for "{0}".
help.multicall=Invokes multiple XML-RPC calls on this server and returns all the results. \r\n\
Parameter: Array of structs, each containing a string 'methodName' and an array 'params', \
each of which specifies an XML-RPC method to call. \r\n\
Returns: An array of elements, either single-element arrays containing the return value, \
or structs containing an int 'faultCode' and a string 'faultString'. \r\n\
(See also Eric Kidd's RFC, <http://www.xmlrpc.com/discuss/msgReader$1208>.)
help.v1.arrayOf=Part of the XML-RPC.COM Validation Suite. \r\n\
Parameter: An array of structs, each of which contains at least three elements, 'moe', \
'larry', and 'curly', all of type number. \r\n\
Returns: The sum of all 'curly' structure elements.
help.v1.countEnt=Part of the XML-RPC.COM Validation Suite. \r\n\
Parameter: A string which may contain any number of left angle brackets, right angle \
brackets, ampersands, apostrophes, and quotes. \r\n\
Returns: A struct with 5 members, all numbers, 'ctLeftAngleBrackets', \
'ctRightAngleBrackets', 'ctAmpersands', 'ctApostrophes', and 'ctQuotes', containing the \
number of left angle brackets, right angle brackets, ampersands, apostrophes, and quotes \
in the string, respectively.
help.v1.ezStruct=Part of the XML-RPC.COM Validation Suite. \r\n\
Parameter: A structure which contains three elements, 'moe', 'larry', and 'curly', all \
of type number. \r\n\
Returns: The sum of those three elements in the structure.
help.v1.echoStr=Part of the XML-RPC.COM Validation Suite. \r\n\
Parameter: An arbitrary struct. \r\nReturns: That same struct.
help.v1.manyType=Part of the XML-RPC.COM Validation Suite. \r\n\
Parameters: Six, all of different types.\r\nReturns: An array containing those six \
parameters, in order.
help.v1.mSAC=Part of the XML-RPC.COM Validation Suite. \r\n\
Parameter: An array containing between 100 and 200 string values. \r\n\
Returns: A string concatenating the first and last elements of the array.
help.v1.nestStr=Part of the XML-RPC.COM Validation Suite. \r\n\
Parameter: A struct modeling a daily calendar. It contains one struct for each year,
with one struct for each month under that (identified by 2-digit numbers with leading
zeroes, January is "01"), and one struct for each day under that (again, the days are
2-digit numbers with leading zeroes). \r\n\
Returns: From the entry in the nested structure for April 1, 2000 ("2000.04.01"), \
the sum of the three number elements in that structure named 'moe', 'larry', and 'curly'.
help.v1.simple=Part of the XML-RPC.COM Validation Suite. \r\n\
Parameter: A single number.\r\nReturns: A struct containing three number elements, 'times10', \
'times100', and 'times1000', which contain the parameter value multiplied by 10, 100, and \
1000, respectively.
help.getCaps=Returns the capabilities supported by this server. \r\n\
Returns: A struct with each entry named according to the spec it refers to. Each entry's value \
is a struct containing two entries, 'specUrl' (a string) and 'specVersion' (a number).
help.listMeth=Lists all methods implemented by the XML-RPC server. \r\n\
Returns: Array of strings, each of which is a method name implemented by the server.
help.methSig=Returns method signatures associated with a method name. \r\n\
Parameter: The method name to examine. \r\n\
Returns: An array of method signatures, each of which is an array of type names. The first name \
in each array is the return type, the others are the parameter types, in order.
help.methHelp=Returns help string associated with a method name. \r\n\
Parameter: The method name to examine. \r\n\
Returns: A string containing the help for this method, which may contain HTML markup. If no \
help is defined for this method, an empty string is returned.
@@ -0,0 +1,33 @@
/*
* 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.dynamo.xmlrpc;
public class XmlRpcMethodNotFound extends SystemFaultCode
{
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public XmlRpcMethodNotFound(String method_name)
{
super(METHOD_NOT_FOUND,"method not found: " + method_name);
} // end constructor
} // end class XmlRpcMethodNotFound
@@ -0,0 +1,39 @@
/*
* 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.dynamo.xmlrpc;
public class XmlRpcParameterError extends SystemFaultCode
{
/*--------------------------------------------------------------------------------
* Constructors
*--------------------------------------------------------------------------------
*/
public XmlRpcParameterError(String message)
{
super(INVALID_PARAMS,message);
} // end constructor
public XmlRpcParameterError(String message, Throwable inner)
{
super(INVALID_PARAMS,message,inner);
} // end constructor
} // end class XmlRpcParameterError
@@ -0,0 +1,700 @@
/*
* 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-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.xmlrpc;
import java.io.*;
import java.text.*;
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.w3c.dom.*;
import com.silverwrist.util.*;
import com.silverwrist.util.xml.*;
import com.silverwrist.dynamo.RequestType;
import com.silverwrist.dynamo.Verb;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.util.*;
/**
* Implements the {@link com.silverwrist.dynamo.iface.Request Request} interface for all XML-RPC requests; parses
* the request body.
*
* @author Eric J. Bowersox &lt;erbo@silcom.com&gt;
* @version X
*/
class XmlRpcRequest extends BaseDelegatingServiceProvider implements Request
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static final String EMPTY_STRING = "";
// Indicates the types of values associated with the request.
private static final int ITYP_INTEGER = 0; // integer
private static final int ITYP_BOOLEAN = 1; // Boolean
private static final int ITYP_STRING = 2; // string
private static final int ITYP_DOUBLE = 3; // double
private static final int ITYP_DATETIME = 4; // date/time
private static final int ITYP_BINARY = 5; // binary (byte array)
private static final int ITYP_STRUCT = 6; // struct (Map)
private static final int ITYP_ARRAY = 7; // array (List)
private static final Map MAP_TYPE; // maps element names to type values
private static final DateFormat s_iso8601; // used to format and parse date/time values
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private HttpServletRequest m_req; // associated HTTP request
private String m_method; // XML-RPC method
private HashMap m_params = new HashMap(); // parameters
private Locale[] m_locales; // locale list
private MemoryObjectStore m_attrs; // scratchpad for attributes
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
/**
* Creates a new XML-RPC request, parsing the request body to get the actual request data.
*
* @param req The original <CODE>HttpServletRequest</CODE> passed to the servlet.
* @param verb The verb associated with this request.
* @param services A {@link com.silverwrist.dynamo.iface.ServiceProvider ServiceProvider} object controlling
* access to request services.
* @param prev The previous {@link com.silverwrist.dynamo.iface.Request Request} object. May be <CODE>null</CODE>.
* @exception com.silverwrist.dynamo.except.RequestParseException If the request data is grossly wrong (these
* errors are reported as HTTP error codes).
* @exception com.silverwrist.dynamo.xmlrpc.FaultCode If an error occurs in parsing the request (these errors
* are reported as XML-RPC faults).
*/
XmlRpcRequest(HttpServletRequest req, Verb verb, ServiceProvider services, Request prev)
throws RequestParseException, FaultCode
{
super("XmlRpcRequest",services);
if (!(Verb.POST.equals(verb)))
throw new RequestParseException("XML-RPC requests must be POST requests");
String ctype = req.getContentType();
if (!(ctype.startsWith("text/xml")))
throw new RequestParseException("XML-RPC requests must have an XML content type");
XMLLoader loader = XMLLoader.get();
Document request_doc = null;
try
{ // parse the XML request
request_doc = loader.load(req.getInputStream(),false);
} // end try
catch (XMLLoadException e)
{ // parse error in XML body...
throw new SystemFaultCode(SystemFaultCode.PARSE_ERROR,e);
} // end catch
catch (IOException e)
{ // I/O error in XML body...
throw new SystemFaultCode(SystemFaultCode.PARSE_ERROR,e);
} // end catch
try
{ // load the XML body of the request, get the method name and parameters
Element method_call = loader.getRootElement(request_doc,"methodCall");
DOMElementHelper method_call_h = new DOMElementHelper(method_call);
m_method = loader.getSubElementText(method_call_h,"methodName");
Element params_elt = method_call_h.getSubElement("params");
if (params_elt!=null)
{ // get all <param/> elements from under <params/> and process them
List l = loader.getMatchingSubElements(params_elt,"param");
int ndx = 0;
Iterator it = l.iterator();
while (it.hasNext())
{ // get the <value/> subelement from each <param/> and store it
Element elt = (Element)(it.next());
Element value_elt = loader.getSubElement(elt,"value");
m_params.put(String.valueOf(ndx++),parseValue(value_elt));
} // end while
} // end if (parameters present)
} // end try
catch (XMLLoadException e)
{ // translate XML exceptions into RequestParseExceptions
throw new SystemFaultCode(SystemFaultCode.INVALID_REQUEST,e);
} // end catch
m_req = req;
m_locales = new Locale[1];
m_locales[0] = Locale.getDefault();
m_attrs = new MemoryObjectStore(XmlRpcRequest.class.getName(),prev);
} // end constructor
/*--------------------------------------------------------------------------------
* Internal operations
*--------------------------------------------------------------------------------
*/
/**
* Parses an XML-RPC &lt;value/&gt; element.
*
* @param elt The node coresponding to the &lt;value/&gt; element.
* @return The parsed value.
* @exception com.silverwrist.dynamo.xmlrpc.FaultCode If an error occurs in parsing the value.
*/
private static final Object parseValue(Element elt) throws FaultCode
{
NodeList nl = elt.getChildNodes();
Element type_spec = null;
for (int i=0; i<nl.getLength(); i++)
{ // look through the subelements to find the type-specific element
Node n = nl.item(i);
if (n.getNodeType()!=Node.ELEMENT_NODE)
continue;
if (type_spec!=null)
throw new SystemFaultCode(SystemFaultCode.INVALID_REQUEST,
"more than one type-specifying element within a <value/> element");
type_spec = (Element)n;
} // end for
Object rc = null;
if (type_spec!=null)
{ // figure out what type this element is
Integer tval = (Integer)(MAP_TYPE.get(type_spec.getTagName()));
if (tval==null)
throw new SystemFaultCode(SystemFaultCode.INVALID_REQUEST,"invalid type \"" + type_spec.getTagName()
+ "\"");
DOMElementHelper h = new DOMElementHelper(type_spec);
switch (tval.intValue())
{ // based on the type, act on the contents
case ITYP_INTEGER:
try
{ // parse the integer value
rc = new Integer(Integer.parseInt(h.getElementText(),10));
} // end try
catch (NumberFormatException e)
{ // value wasn't an integer
throw new SystemFaultCode(SystemFaultCode.INVALID_REQUEST,"invalid integer format",e);
} // end catch
catch (NullPointerException e)
{ // value was null
throw new SystemFaultCode(SystemFaultCode.INVALID_REQUEST,"integer value not specified");
} // end catch
break;
case ITYP_BOOLEAN:
{ // test the Boolean value
String s = h.getElementText();
if (s==null)
throw new SystemFaultCode(SystemFaultCode.INVALID_REQUEST,"boolean value not specified");
if (s.equals("1"))
rc = Boolean.TRUE;
else if (s.equals("0"))
rc = Boolean.FALSE;
else
throw new SystemFaultCode(SystemFaultCode.INVALID_REQUEST,"invalid boolean format");
} // end case
break;
case ITYP_STRING:
{ // get the string value and return it
rc = h.getElementText();
if (rc==null)
rc = EMPTY_STRING;
} // end case
break;
case ITYP_DOUBLE:
try
{ // convert to a Double value
rc = new Double(h.getElementText());
} // end try
catch (NumberFormatException e)
{ // value wasn't an integer
throw new SystemFaultCode(SystemFaultCode.INVALID_REQUEST,"invalid double format",e);
} // end catch
catch (NullPointerException e)
{ // value was null
throw new SystemFaultCode(SystemFaultCode.INVALID_REQUEST,"double value not specified");
} // end catch
break;
case ITYP_DATETIME:
try
{ // convert to a Date value
rc = s_iso8601.parse(h.getElementText());
} // end try
catch (java.text.ParseException e)
{ // date couldn't be parsed
throw new SystemFaultCode(SystemFaultCode.INVALID_REQUEST,"invalid ISO 8601 date format",e);
} // end catch
catch (NullPointerException e)
{ // no value in there...
throw new SystemFaultCode(SystemFaultCode.INVALID_REQUEST,"date value not specified");
} // end catch
break;
case ITYP_BINARY:
try
{ // get the string equivalent of the formatted data
String s = h.getElementText();
if (s==null)
{ // null string - return null array
rc = new byte[0];
break;
} // end if
// get a stream of encoded bytes
ByteArrayInputStream encoded_stm = new ByteArrayInputStream(s.getBytes("US-ASCII"));
// use the JavaMail MIME decoder to turn it into decoded bytes
InputStream decoded_stm = MimeUtility.decode(encoded_stm,"base64");
// copy the decoded bytes to a new array
ByteArrayOutputStream output = new ByteArrayOutputStream();
IOUtils.copy(decoded_stm,output);
IOUtils.shutdown(decoded_stm);
IOUtils.shutdown(encoded_stm);
// retrieve the output array
rc = output.toByteArray();
IOUtils.shutdown(output);
} // end try
catch (UnsupportedEncodingException e)
{ // WTF? shouldn't happen
throw new SystemFaultCode(SystemFaultCode.INTERNAL_ERROR,"internal error: unsupported encoding",e);
} // end catch
catch (IOException e)
{ // some sort of error copying binary values around
throw new SystemFaultCode(SystemFaultCode.INTERNAL_ERROR,"unable to get binary data",e);
} // end catch
catch (MessagingException e)
{ // error in the MIME parsing - dump it out
throw new SystemFaultCode(SystemFaultCode.INVALID_REQUEST,"invalid binary data format",e);
} // end catch
break;
case ITYP_STRUCT:
rc = parseStruct(type_spec);
break;
case ITYP_ARRAY:
rc = parseArray(type_spec);
break;
default:
throw new SystemFaultCode(SystemFaultCode.INVALID_REQUEST,"invalid type \""
+ type_spec.getTagName() + "\"");
} // end switch
} // end if
else
{ // if there's no type-specifying element, treat it as a String
DOMElementHelper h = new DOMElementHelper(elt);
rc = h.getElementText();
if (rc==null)
rc = EMPTY_STRING;
} // end else
return rc;
} // end parseValue
/**
* Parses an XML-RPC &lt;struct/&gt; element.
*
* @param elt The node coresponding to the &lt;struct/&gt; element.
* @return The parsed value.
* @exception com.silverwrist.dynamo.xmlrpc.FaultCode If an error occurs in parsing the value.
*/
private static final Map parseStruct(Element elt) throws FaultCode
{
XMLLoader loader = XMLLoader.get();
HashMap rc = new HashMap();
try
{ // get all <member/> sub-elements and process them
List l = loader.getMatchingSubElements(elt,"member");
Iterator it = l.iterator();
while (it.hasNext())
{ // get each <member/> and add its <name/> and <value/> to the map
Element x = (Element)(it.next());
DOMElementHelper h = new DOMElementHelper(x);
String name = loader.getSubElementText(h,"name");
Element val_elt = loader.getSubElement(h,"value");
rc.put(name,parseValue(val_elt));
} // end while
} // end try
catch (XMLLoadException e)
{ // translate load exception
throw new SystemFaultCode(SystemFaultCode.INVALID_REQUEST,e);
} // end catch
if (rc.isEmpty())
return Collections.EMPTY_MAP;
else
return Collections.unmodifiableMap(rc);
} // end parseStruct
/**
* Parses an XML-RPC &lt;array/&gt; element.
*
* @param elt The node coresponding to the &lt;array/&gt; element.
* @return The parsed value.
* @exception com.silverwrist.dynamo.xmlrpc.FaultCode If an error occurs in parsing the value.
*/
private static final List parseArray(Element elt) throws FaultCode
{
XMLLoader loader = XMLLoader.get();
ArrayList rc = null;
try
{ // get the <data/> sub-element
Element data_elt = loader.getSubElement(elt,"data");
// get the values it contains
List l = loader.getMatchingSubElements(data_elt,"value");
rc = new ArrayList(l.size());
Iterator it = l.iterator();
while (it.hasNext())
{ // parse the <value/> elements and add them to the list
Element val_elt = (Element)(it.next());
rc.add(parseValue(val_elt));
} // end while
} // end try
catch (XMLLoadException e)
{ // translate load exception
throw new SystemFaultCode(SystemFaultCode.INVALID_REQUEST,e);
} // end catch
if ((rc==null) || rc.isEmpty())
return Collections.EMPTY_LIST;
else
return Collections.unmodifiableList(rc);
} // end parseArray
/*--------------------------------------------------------------------------------
* Implementations from interface ObjectProvider
*--------------------------------------------------------------------------------
*/
/**
* Retrieves an object from this <CODE>ObjectProvider</CODE>.
*
* @param namespace The namespace to interpret the name relative to.
* @param name The name of the object to be retrieved.
* @return The object reference specified.
*/
public Object getObject(String namespace, String name)
{
return m_attrs.getObject(namespace,name);
} // end getObject
/*--------------------------------------------------------------------------------
* Implementations from interface ObjectStore
*--------------------------------------------------------------------------------
*/
/**
* Sets an object into this <CODE>ObjectStore</CODE>.
*
* @param namespace The namespace to interpret the name relative to.
* @param name The name of the object to be set.
* @param value The object to set into the <CODE>ObjectStore</CODE>.
* @return The previous object that was set into the <CODE>ObjectStore</CODE> under this namespace and name, or
* <CODE>null</CODE> if there was no such object.
*/
public Object setObject(String namespace, String name, Object value)
{
return m_attrs.setObject(namespace,name,value);
} // end setObject
/**
* Removes an object from this <CODE>ObjectStore</CODE>.
*
* @param namespace The namespace to interpret the name relative to.
* @param name The name of the object to be removed.
* @return The previous object that was set into the <CODE>ObjectStore</CODE> under this namespace and name, or
* <CODE>null</CODE> if there was no such object.
*/
public Object removeObject(String namespace, String name)
{
return m_attrs.removeObject(namespace,name);
} // end removeObject
/**
* Returns a collection of all object namespaces that have been set into this <CODE>ObjectStore</CODE>.
*
* @return A <CODE>java.util.Collection</CODE> containing <CODE>String</CODE> objects specifying all the
* object namespaces.
*/
public Collection getNamespaces()
{
return m_attrs.getNamespaces();
} // end getNamespaces
/**
* Returns a collection of all object names that have been set into this <CODE>ObjectStore</CODE> under a given
* namespace.
*
* @param namespace The namespace to look for names under.
* @return A <CODE>java.util.Collection</CODE> containing <CODE>String</CODE> objects specifying all the
* object names for this namespace.
*/
public Collection getNamesForNamespace(String namespace)
{
return m_attrs.getNamesForNamespace(namespace);
} // end getNamesForNamespace
/*--------------------------------------------------------------------------------
* Implementations from interface Request
*--------------------------------------------------------------------------------
*/
/**
* Returns a value indicating the type of this request.
*
* @return The type of this request.
* @see com.silverwrist.dynamo.RequestType#XMLRPC
*/
public RequestType getType()
{
return RequestType.XMLRPC;
} // end getType
/**
* Returns the DNS name or IP address of the server to which the request was made.
*
* @return The server name to which the request was name.
*/
public String getServerName()
{
return m_req.getServerName();
} // end getServerName
/**
* Returns the number of the port on which this request was made.
*
* @return The port number on which the request was made, or -1 if it could not be determined.
*/
public int getServerPort()
{
return m_req.getServerPort();
} // end getServerPort
/**
* Returns the portion of the request URI that indicates the context of the request. The context path always comes
* first in a request URI. The path starts with a "/" character but does not end with a "/" character. For servlets
* in the default (root) context, this method returns "". The servlet container does not decode this string.
*
* @return The context path of the request.
*/
public String getContextPath()
{
return m_req.getContextPath();
} // end getContextPath
/**
* Returns the part of this request's URL that calls the endpoint. This includes either the endpoint name or a path
* to the endpoint, but does not include any extra path information or a query string. For XML-RPC requests,
* this will usually be the value "/RPC2".
*
* @return The request path of this request.
*/
public String getRequestPath()
{
return m_req.getServletPath();
} // end getRequestPath
/**
* Returns any extra path information associated with the URL the client sent when it made this request. The extra
* path information follows the request path but precedes the query string. This method returns <CODE>null</CODE>
* if there was no extra path information.
*
* @return The "extra path" of this request. If there is no "extra path," returns <CODE>null</CODE>.
*/
public String getExtraPath()
{
return null;
} // end getExtraPath
/**
* Returns the query string that is contained in the request URL after the path. For XML-RPC requests, this is
* the name of the method that was called.
*
* @return The method name associated with this request.
*/
public String getQueryString()
{
return m_method;
} // end getQueryString
/**
* Returns a value indicating the action associated with this request. For XML-RPC requests, this verb is
* always {@link com.silverwrist.dynamo.Verb#POST POST}.
*
* @return The action associated with this request.
* @see com.silverwrist.dynamo.Verb
*/
public Verb getVerb()
{
return Verb.POST;
} // end getVerb
/**
* Returns a string representation of the IP address of the client that made this request.
*
* @return The address of the client making the request.
*/
public String getSourceAddress()
{
return m_req.getRemoteAddr();
} // end getSourceAddress
/**
* Returns a java.util.Map of the parameters of this request. For XML-RPC requests, these parameters are passed
* as an array associated with the method call.
* <P>The keys of the map are <CODE>String</CODE> objects; the values of the map are arrays of the type specified
* by the return value of {@link #getParametersEntryClass() getParametersEntryClass()}. For XML-RPC, the keys
* are printable-string equivalents of integers representing the parameters' position.
*
* @return The parameter map, as specified above. This map is read-only.
*/
public Map getParameters()
{
return Collections.unmodifiableMap(m_params);
} // end getParameters
/**
* Returns a class specifying the fundamental type of objects contained in the arrays acting as the values of
* the map returned by {@link #getParameters() getParameters()}. For XML-RPC, this class is <CODE>Object</CODE>,
* indicating that the contained objects may be of any type, as the parser has already figured out their precise
* type.
*
* @return The class of array elements within the parameter map.
*/
public Class getParametersEntryClass()
{
return Object.class;
} // end getParametersEntryClass
/**
* Returns a java.util.Map of the data items of this request. Data items are lengthy streams of data associated
* with a request. XML-RPC requests have no data items associated with them.
*
* @return The data item map, as specified above. This map is read-only.
*/
public Map getDataItems()
{
return Collections.EMPTY_MAP;
} // end getDataItems
/**
* Returns an array of <CODE>Locale</CODE> objects indicating, in decreasing order starting with the preferred
* locale, the locales that are acceptable to the client based on an <CODE>Accept-Language</CODE> header or similar.
* method. If the client request doesn't provide an <CODE>Accept-Language</CODE> header or similar indication,
* this method returns an array containing one <CODE>Locale</CODE>, the default locale for the server.
*
* @return An array of preferred <CODE>Locale</CODE> objects for the client.
*/
public Locale[] getLocales()
{
return m_locales;
} // end getLocales
/*--------------------------------------------------------------------------------
* Static initializer
*--------------------------------------------------------------------------------
*/
static
{ // Initialize the type map.
HashMap tmp = new HashMap();
Integer foo = new Integer(ITYP_INTEGER);
tmp.put("i4",foo);
tmp.put("int",foo);
tmp.put("boolean",new Integer(ITYP_BOOLEAN));
tmp.put("string",new Integer(ITYP_STRING));
tmp.put("double",new Integer(ITYP_DOUBLE));
tmp.put("dateTime.iso8601",new Integer(ITYP_DATETIME));
tmp.put("base64",new Integer(ITYP_BINARY));
tmp.put("struct",new Integer(ITYP_STRUCT));
tmp.put("array",new Integer(ITYP_ARRAY));
MAP_TYPE = Collections.unmodifiableMap(tmp);
// Initialize the ISO 8601 date formatter.
SimpleDateFormat iso = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
iso.setCalendar(new GregorianCalendar(new SimpleTimeZone(0,"UTC")));
s_iso8601 = iso;
} // end static initializer
} // end class XmlRpcRequest
@@ -0,0 +1,619 @@
/*
* 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.dynamo.xmlrpc;
import java.io.*;
import java.lang.ref.Reference;
import java.sql.Blob;
import java.sql.SQLException;
import java.text.*;
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
import com.silverwrist.util.*;
import com.silverwrist.dynamo.HttpStatusCode;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
public class XmlRpcResult implements SelfRenderable, XmlRpcSelfSerializing
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static final String SERIALIZED_NULL = "<string>null</string>";
private static final String START_ARRAY = "<array><data>\r\n";
private static final String END_ARRAY = "</data></array>";
private static final String START_VALUE = "<value>";
private static final String END_VALUE = "</value>\r\n";
private static final DateFormat s_iso8601;
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private Object m_obj;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public XmlRpcResult(Object obj)
{
m_obj = obj;
} // end constructor
/*--------------------------------------------------------------------------------
* Implementations from interface SelfRenderable
*--------------------------------------------------------------------------------
*/
public void render(SelfRenderControl control) throws IOException, RenderingException
{
// Serialize the output value to a StringWriter.
StringWriter wr = new StringWriter();
wr.write("<methodResponse><params><param>\r\n<value>");
serialize(wr,m_obj);
wr.write("</value>\r\n</param></params></methodResponse>\r\n");
// Now render the binary equivalent of this structure.
byte[] data = null;
try
{ // get a complete rendering of this data
data = wr.toString().getBytes("UTF-8");
} // end try
catch (UnsupportedEncodingException e)
{ // WTF? shouldn't happen
data = wr.toString().getBytes();
} // end catch
// send out the bytes as an XML message body
control.status(HttpStatusCode.S_OK);
BinaryRenderControl bctrl = control.getBinaryRender();
bctrl.setContentType("text/xml; charset=UTF-8");
bctrl.setContentLength(data.length);
OutputStream stm = bctrl.getStream();
stm.write(data);
stm.flush();
} // end render
/*--------------------------------------------------------------------------------
* Implementations from interface XmlRpcSelfSerializing
*--------------------------------------------------------------------------------
*/
public void serializeXmlRpc(Writer wr) throws IOException
{
serialize(wr,m_obj);
} // end serializeXmlRpc
/*--------------------------------------------------------------------------------
* External static operations
*--------------------------------------------------------------------------------
*/
public static void serializeBinary(Writer wr, InputStream stm) throws IOException
{
try
{ // Encode the data as BASE-64.
ByteArrayOutputStream internal_stm = new ByteArrayOutputStream();
OutputStream encode_stm = MimeUtility.encode(internal_stm,"base64");
IOUtils.copy(stm,encode_stm);
encode_stm.flush();
// turn our encoded output into an InputStream
ByteArrayInputStream internal2_stm = new ByteArrayInputStream(internal_stm.toByteArray());
IOUtils.shutdown(encode_stm);
IOUtils.shutdown(internal_stm);
// write out the data
InputStreamReader rd = new InputStreamReader(internal2_stm,"US-ASCII");
wr.write("<base64>");
IOUtils.copy(rd,wr);
wr.write("</base64>");
IOUtils.shutdown(rd);
IOUtils.shutdown(internal2_stm);
} // end try
catch (MessagingException e)
{ // encoder might have an error
throw new IOException("error encoding binary data");
} // end catch
} // end serializeBinary
public static void serialize(Writer wr, boolean b) throws IOException
{
wr.write("<boolean>");
wr.write(b ? "1" : "0");
wr.write("</boolean>");
} // end serialize
public static void serialize(Writer wr, boolean[] b) throws IOException
{
wr.write(START_ARRAY);
for (int i=0; i<b.length; i++)
{ // serialize the values we contain
wr.write(START_VALUE);
serialize(wr,b[i]);
wr.write(END_VALUE);
} // end for
wr.write(END_ARRAY);
} // end serialize
public static void serialize(Writer wr, byte b) throws IOException
{
serialize(wr,(int)b);
} // end serialize
public static void serialize(Writer wr, byte[] b) throws IOException
{
serializeBinary(wr,new ByteArrayInputStream(b));
} // end serialize
public static void serialize(Writer wr, char c) throws IOException
{
wr.write("<string>");
wr.write(c);
wr.write("</string>");
} // end serialize
public static void serialize(Writer wr, char[] c) throws IOException
{
wr.write(START_ARRAY);
for (int i=0; i<c.length; i++)
{ // serialize the values we contain
wr.write(START_VALUE);
serialize(wr,c[i]);
wr.write(END_VALUE);
} // end for
wr.write(END_ARRAY);
} // end serialize
public static void serialize(Writer wr, short s) throws IOException
{
serialize(wr,(int)s);
} // end serialize
public static void serialize(Writer wr, short[] s) throws IOException
{
wr.write(START_ARRAY);
for (int i=0; i<s.length; i++)
{ // serialize the values we contain
wr.write(START_VALUE);
serialize(wr,s[i]);
wr.write(END_VALUE);
} // end for
wr.write(END_ARRAY);
} // end serialize
public static void serialize(Writer wr, int i) throws IOException
{
wr.write("<int>");
wr.write(String.valueOf(i));
wr.write("</int>");
} // end serialize
public static void serialize(Writer wr, int[] ia) throws IOException
{
wr.write(START_ARRAY);
for (int i=0; i<ia.length; i++)
{ // serialize the values we contain
wr.write(START_VALUE);
serialize(wr,ia[i]);
wr.write(END_VALUE);
} // end for
wr.write(END_ARRAY);
} // end serialize
public static void serialize(Writer wr, long l) throws IOException
{
serialize(wr,(double)l);
} // end serialize
public static void serialize(Writer wr, long[] l) throws IOException
{
wr.write(START_ARRAY);
for (int i=0; i<l.length; i++)
{ // serialize the values we contain
wr.write(START_VALUE);
serialize(wr,l[i]);
wr.write(END_VALUE);
} // end for
wr.write(END_ARRAY);
} // end serialize
public static void serialize(Writer wr, float f) throws IOException
{
serialize(wr,(double)f);
} // end serialize
public static void serialize(Writer wr, float[] f) throws IOException
{
wr.write(START_ARRAY);
for (int i=0; i<f.length; i++)
{ // serialize the values we contain
wr.write(START_VALUE);
serialize(wr,f[i]);
wr.write(END_VALUE);
} // end for
wr.write(END_ARRAY);
} // end serialize
public static void serialize(Writer wr, double d) throws IOException
{
wr.write("<double>");
wr.write(String.valueOf(d));
wr.write("</double>");
} // end serialize
public static void serialize(Writer wr, double[] d) throws IOException
{
wr.write(START_ARRAY);
for (int i=0; i<d.length; i++)
{ // serialize the values we contain
wr.write(START_VALUE);
serialize(wr,d[i]);
wr.write(END_VALUE);
} // end for
wr.write(END_ARRAY);
} // end serialize
public static void serializeCalendar(Writer wr, Calendar cal) throws IOException
{
wr.write("<dateTime.iso8601>");
// Encode the year first.
StringBuffer conv = new StringBuffer("0000");
conv.append(cal.get(Calendar.YEAR));
String c = conv.toString();
wr.write(c.substring(c.length()-4));
// Now the month...
conv.setLength(0);
conv.append("00").append(cal.get(Calendar.MONTH) - Calendar.JANUARY + 1);
c = conv.toString();
wr.write(c.substring(c.length()-2));
// And the day...
conv.setLength(0);
conv.append("00").append(cal.get(Calendar.DAY_OF_MONTH));
c = conv.toString();
wr.write(c.substring(c.length()-2));
wr.write("T");
// And the hour...
conv.setLength(0);
conv.append("00").append(cal.get(Calendar.HOUR_OF_DAY));
c = conv.toString();
wr.write(c.substring(c.length()-2));
wr.write(":");
// And the minute...
conv.setLength(0);
conv.append("00").append(cal.get(Calendar.MINUTE));
c = conv.toString();
wr.write(c.substring(c.length()-2));
wr.write(":");
// And the second...
conv.setLength(0);
conv.append("00").append(cal.get(Calendar.SECOND));
c = conv.toString();
wr.write(c.substring(c.length()-2));
// And we're done!
wr.write("</dateTime.iso8601>");
} // end serializeCalendar
public static void serializeCollection(Writer wr, Collection coll) throws IOException
{
serializeIterator(wr,coll.iterator());
} // end serializeCollection
public static void serializeDate(Writer wr, Date d) throws IOException
{
wr.write("<dateTime.iso8601>");
wr.write(s_iso8601.format(d));
wr.write("</dateTime.iso8601>");
} // end serializeDate
public static void serializeEnumeration(Writer wr, Enumeration enum) throws IOException
{
wr.write(START_ARRAY);
while (enum.hasMoreElements())
{ // serialize the values we contain
wr.write(START_VALUE);
serialize(wr,enum.nextElement());
wr.write(END_VALUE);
} // end for
wr.write(END_ARRAY);
} // end serializeIterator
public static void serializeIterator(Writer wr, Iterator it) throws IOException
{
wr.write(START_ARRAY);
while (it.hasNext())
{ // serialize the values we contain
wr.write(START_VALUE);
serialize(wr,it.next());
wr.write(END_VALUE);
} // end for
wr.write(END_ARRAY);
} // end serializeIterator
public static void serializeMap(Writer wr, Map map) throws IOException
{
wr.write("<struct>\r\n");
Iterator it = map.entrySet().iterator();
while (it.hasNext())
{ // write each entry in turn
Map.Entry ntry = (Map.Entry)(it.next());
wr.write("<member>\r\n<name>");
wr.write(StringUtils.encodeHTML(ntry.getKey().toString()));
wr.write("</name>\r\n<value>");
serialize(wr,ntry.getValue());
wr.write("</value>\r\n</member>");
} // end while
wr.write("\r\n</struct>");
} // end serializeMap
public static void serializeString(Writer wr, String s) throws IOException
{
wr.write("<string>");
wr.write(StringUtils.encodeHTML(s));
wr.write("</string>");
} // end serializeString
public static void serialize(Writer wr, Object obj) throws IOException
{
if (obj==null)
{ // null object - bye!
wr.write(SERIALIZED_NULL);
return;
} // end if
if (obj.getClass().isArray())
{ // for arrays, serialize them specially
Class component = obj.getClass().getComponentType();
if (component==Boolean.TYPE)
serialize(wr,(boolean[])obj);
else if (component==Byte.TYPE)
serialize(wr,(byte[])obj);
else if (component==Character.TYPE)
serialize(wr,(char[])obj);
else if (component==Short.TYPE)
serialize(wr,(short[])obj);
else if (component==Integer.TYPE)
serialize(wr,(int[])obj);
else if (component==Long.TYPE)
serialize(wr,(long[])obj);
else if (component==Float.TYPE)
serialize(wr,(float[])obj);
else if (component==Double.TYPE)
serialize(wr,(double[])obj);
else
serialize(wr,(Object[])obj);
return;
} // end if
if (obj instanceof XmlRpcSelfSerializing)
{ // some objects may be self-serializing
((XmlRpcSelfSerializing)obj).serializeXmlRpc(wr);
return;
} // end if
if (obj instanceof DynamicWrapper)
{ // for dynamic wrappers, unwrap them
serialize(wr,((DynamicWrapper)obj).unwrap());
return;
} // end if
if (obj instanceof InputStream)
{ // for InputStream, turn it into binary
serializeBinary(wr,(InputStream)obj);
return;
} // end if
if (obj instanceof Blob)
{ // serialize the blob as a binary stream
try
{ // just get its input stream
serializeBinary(wr,((Blob)obj).getBinaryStream());
return;
} // end try
catch (SQLException e)
{ // fault on error here
throw new IOException("error writing binary data");
} // end catch
} // end if
if (obj instanceof Calendar)
{ // serialize a Calendar
serializeCalendar(wr,(Calendar)obj);
return;
} // end if
if (obj instanceof Collection)
{ // serialize a Collection
serializeCollection(wr,(Collection)obj);
return;
} // end if
if (obj instanceof Date)
{ // serialize a Date
serializeDate(wr,(Date)obj);
return;
} // end if
if (obj instanceof Enumeration)
{ // serialize a Enumeration
serializeEnumeration(wr,(Enumeration)obj);
return;
} // end if
if (obj instanceof Iterator)
{ // serialize a Iterator
serializeIterator(wr,(Iterator)obj);
return;
} // end if
if (obj instanceof Map)
{ // serialize a Map
serializeMap(wr,(Map)obj);
return;
} // end if
if (obj instanceof Reference)
{ // for a Reference, serialize the referent
serialize(wr,((Reference)obj).get());
return;
} // end if
if (obj instanceof Boolean)
{ // serialize the boolean value
serialize(wr,((Boolean)obj).booleanValue());
return;
} // end if
if (obj instanceof Character)
{ // serialize the character value
serialize(wr,((Character)obj).charValue());
return;
} // end if
if ((obj instanceof Byte) || (obj instanceof Short) || (obj instanceof Integer))
{ // serialize the integer value
serialize(wr,((Number)obj).intValue());
return;
} // end if
if ((obj instanceof Long) || (obj instanceof Float) || (obj instanceof Double))
{ // serialize the double value
serialize(wr,((Number)obj).doubleValue());
return;
} // end if
// String and StringBuffer are handled properly by the fallback mechanism below
// last-ditch fallback method - use toString, get the string, and encode it
serializeString(wr,obj.toString());
} // end serialize
public static void serialize(Writer wr, Object[] arr) throws IOException
{
wr.write(START_ARRAY);
for (int i=0; i<arr.length; i++)
{ // serialize the values we contain
wr.write(START_VALUE);
serialize(wr,arr[i]);
wr.write(END_VALUE);
} // end for
wr.write(END_ARRAY);
} // end serialize
/*--------------------------------------------------------------------------------
* Static initializer
*--------------------------------------------------------------------------------
*/
static
{ // Initialize the ISO 8601 date formatter.
SimpleDateFormat iso = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
iso.setCalendar(new GregorianCalendar(new SimpleTimeZone(0,"UTC")));
s_iso8601 = iso;
} // end static initializer
} // end class XmlRpcResult
@@ -0,0 +1,27 @@
/*
* 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.dynamo.xmlrpc;
import java.io.IOException;
import java.io.Writer;
public interface XmlRpcSelfSerializing
{
public void serializeXmlRpc(Writer wr) throws IOException;
} // end interface XmlRpcSelfSerializing
@@ -0,0 +1,160 @@
/*
* 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-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.xmlrpc;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.silverwrist.dynamo.Namespaces;
import com.silverwrist.dynamo.Verb;
import com.silverwrist.dynamo.app.ApplicationContainer;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.servlet.HttpMethod;
import com.silverwrist.dynamo.servlet.ServletBase;
import com.silverwrist.dynamo.util.*;
public class XmlRpcServlet extends ServletBase implements ComponentShutdown
{
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private XmlRpcSubSystem m_subsystem; // pointer to the XML-RPC subsystem
/*--------------------------------------------------------------------------------
* Abstract implementations from class ServletBase
*--------------------------------------------------------------------------------
*/
protected Object process(Request r, Application app) throws Exception
{
try
{ // dispatch the method call
return m_subsystem.dispatch(r,app);
} // end try
catch (FaultCode fc)
{ // return the FaultCode to be output
return fc;
} // end catch
} // end process
/*--------------------------------------------------------------------------------
* Overrides from class ServletBase
*--------------------------------------------------------------------------------
*/
protected void initServlet(ServiceProvider services) throws DynamoException
{
// Get the name of the XML-RPC subsystem object.
ObjectProvider oprov = (ObjectProvider)(services.queryService(ObjectProvider.class));
String subsys_name = (String)(oprov.getObject(Namespaces.SERVLET_INIT_NAMESPACE,"subsystem.object"));
// Get the subsystem object.
m_subsystem = (XmlRpcSubSystem)(GetObjectUtils.getDynamoComponent(services,XmlRpcSubSystem.class,
subsys_name));
} // end initServlet
protected boolean supportsMethod(HttpMethod method, Application app)
{
return HttpMethod.POST.equals(method);
} // end supportsMethod
protected ServiceProvider createRequestServices(HttpServletRequest req, HttpServletResponse resp)
{
// Create the service provider interface and return it.
SimpleServiceProvider services = new SimpleServiceProvider("Request Services");
services.addService(SessionInfoProvider.class,NullSessionInfo.getProvider());
services.addService(BrowserDataProvider.class,createBrowserDataProvider(req));
services.addService(HeaderInput.class,createHeaderInput(req));
services.addService(XmlRpcCreateSession.class,m_subsystem);
return services;
} // end createRequestServices
protected Request createRequest(HttpServletRequest req, Verb verb, ServiceProvider services, Request prev)
throws RequestParseException
{
XmlRpcRequest xreq = null;
try
{ // create our special request type
xreq = new XmlRpcRequest(req,verb,services,prev);
} // end try
catch (FaultCode fc)
{ // "wrap" the FaultCode - we'll get back to it
throw new RequestParseException(fc.getMessage(),fc);
} // end catch
return xreq;
} // end createRequest
protected Object translateRequestParseException(RequestParseException e)
{
Throwable cause = e.getCause();
if ((cause!=null) && (cause instanceof FaultCode))
return cause;
return super.translateRequestParseException(e);
} // end translateRequestParseException
protected Object translateException(Request r, Exception e)
{
return m_subsystem.translateException(r,e);
} // end translateException
protected ServiceProvider createOutputServices(HttpServletRequest req, HttpServletResponse resp)
{
return new SingletonServiceProvider("Rendering Services",BrowserDataProvider.class,
createBrowserDataProvider(req));
} // end createOutputServices
protected void outputResult(HttpServletRequest req, HttpServletResponse resp,
ServiceProvider services, Object result) throws IOException, RenderingException
{
if (result instanceof FaultCode)
super.outputResult(req,resp,services,result);
else if (result instanceof XmlRpcResult)
super.outputResult(req,resp,services,result);
else
super.outputResult(req,resp,services,new XmlRpcResult(result));
} // end outputResult
/*--------------------------------------------------------------------------------
* Implementations from interface ComponentShutdown
*--------------------------------------------------------------------------------
*/
public void shutdown()
{
m_subsystem = null;
} // end shutdown
} // end class XmlRpcServlet
@@ -0,0 +1,463 @@
/*
* 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-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.xmlrpc;
import java.util.*;
import org.apache.log4j.Logger;
import com.silverwrist.dynamo.RequestType;
import com.silverwrist.dynamo.app.ApplicationContainer;
import com.silverwrist.dynamo.event.*;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.util.*;
/**
* An implementation of {@link com.silverwrist.dynamo.iface.SessionInfo SessionInfo} that is managed
* by the {@link com.silverwrist.dynamo.xmlrpc.XmlRpcSubSystem XmlRpcSubSystem}. Many XML-RPC
* requests bear a "session ID" value, which is used to look up their session in a map maintained
* by the subsystem.
*
* @author Eric J. Bowersox &lt;erbo@silcom.com&gt;
* @version X
*/
class XmlRpcSessionInfo implements SessionInfo, ComponentShutdown
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static Logger logger = Logger.getLogger(XmlRpcSessionInfo.class);
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private XmlRpcSubSystem m_subsystem; // backreference to the XML-RPC subsystem
private ApplicationContainer m_appcon; // backreference to the application container
private String m_id; // ID of this session
private MemoryObjectStore m_store; // where we put all our session attributes
private long m_created; // time of creation
private long m_last_access; // time of last access
private int m_max_inactive; // maximum inactive interval in seconds
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
/**
* Constructs a new <CODE>XmlRpcSessionInfo</CODE> instance.
*
* @param subsystem The XML-RPC subsystem object.
* @param appcon The {@link com.silverwrist.dynamo.app.ApplicationContainer} for the application.
* @param id The ID for the new session.
*/
XmlRpcSessionInfo(XmlRpcSubSystem subsystem, ApplicationContainer appcon, String id)
{
m_subsystem = subsystem;
m_appcon = appcon;
m_id = id;
m_store = new MemoryObjectStore("Session Store " + m_id);
m_max_inactive = subsystem.getDefaultMaxAge();
m_created = m_last_access = System.currentTimeMillis();
} // end constructor
/*--------------------------------------------------------------------------------
* Internal operations
*--------------------------------------------------------------------------------
*/
/**
* Shuts down the session. It sends out session-exiting notifications, unbinds all variables from the
* session, and erases the contents.
*/
private final void destroy()
{
logger.info("Calling sessionExiting notifications on session " + m_id);
// Send the end-session notifications.
SessionInfoListener[] listeners = m_appcon.getSessionListeners();
if (listeners.length>0)
{ // call each listener in turn
SessionEventRequest req = new SessionEventRequest(m_appcon.wrapServices(null),this,false);
SessionInfoEvent evt = new SessionInfoEvent(req,this);
for (int i=0; i<listeners.length; i++)
listeners[i].sessionExiting(evt);
} // end if
// Tell all the values in the object store they're being kicked out.
m_store.visitAllContents(new ObjectVisitor()
{
public void visit(String namespace, String name, Object value)
{
if (value instanceof SessionValueBindListener)
((SessionValueBindListener)value).valueRemoved(new SessionValueBindEvent(XmlRpcSessionInfo.this,
namespace,name));
} // end visit
}); // end ObjectVisitor object
// Detach all data.
m_store.clear();
m_store = null;
m_subsystem = null;
} // end destroy
/*--------------------------------------------------------------------------------
* Overrides from class Object
*--------------------------------------------------------------------------------
*/
/**
* Indicates whether some other object is "equal to" this one.
*
* @param o The reference object with which to compare.
* @return <CODE>true</CODE> if this object is the same as the <CODE>o</CODE> argument; <CODE>false</CODE> otherwise.
*/
public boolean equals(Object o)
{
if ((o==null) || !(o instanceof XmlRpcSessionInfo))
return false;
SessionInfo other = (SessionInfo)o;
return m_id.equals(other.getID());
} // end equals
/**
* Returns a hash code value for the object. This method is supported for the benefit of hashtables such as those
* provided by <CODE>java.util.Hashtable</CODE>.
*
* @return A hash code value for this object.
*/
public int hashCode()
{
return m_id.hashCode();
} // end hashCode
/**
* Returns a string representation of the object. In general, the <CODE>toString</CODE> method returns a string
* that "textually represents" this object.
*
* @return A string representation of the object.
*/
public String toString()
{
return "{XmlRpcSessionInfo id=" + m_id + "}";
} // end toString
/*--------------------------------------------------------------------------------
* Implementations from interface ObjectProvider
*--------------------------------------------------------------------------------
*/
/**
* Retrieves an object from this session's <CODE>ObjectProvider</CODE>.
*
* @param namespace The namespace to interpret the name relative to.
* @param name The name of the object to be retrieved.
* @return The object reference specified.
*/
public Object getObject(String namespace, String name)
{
if (namespace==null)
throw new NullPointerException("XmlRpcSessionInfo.getObject(namespace)");
if (name==null)
throw new NullPointerException("XmlRpcSessionInfo.getObject(name)");
return m_store.getObject(namespace,name);
} // end getObject
/*--------------------------------------------------------------------------------
* Implementations from interface ObjectStore
*--------------------------------------------------------------------------------
*/
/**
* Sets an object into this session's <CODE>ObjectStore</CODE>. If the object implements
* {@link com.silverwrist.dynamo.event.SessionValueBindListener SessionValueBindListener}, its
* {@link com.silverwrist.dynamo.event.SessionValueBindListener#valueAdded(com.silverwrist.dynamo.event.SessionValueBindEvent) valueAdded()}
* method will be called. If there was an object previously stored in this <CODE>ObjectStore</CODE> with the given
* namespace and name, and it implements <CODE>SessionValueBindListener</CODE>, its
* {@link com.silverwrist.dynamo.event.SessionValueBindListener#valueReplaced(com.silverwrist.dynamo.event.SessionValueBindEvent) valueReplaced()}
* method will be called.
*
* @param namespace The namespace to interpret the name relative to.
* @param name The name of the object to be set.
* @param value The object to set into the <CODE>ObjectStore</CODE>.
* @return The previous object that was set into the <CODE>ObjectStore</CODE> under this namespace and name, or
* <CODE>null</CODE> if there was no such object.
*/
public Object setObject(String namespace, String name, Object value)
{
if (namespace==null)
throw new NullPointerException("XmlRpcSessionInfo.setObject(namespace)");
if (name==null)
throw new NullPointerException("XmlRpcSessionInfo.setObject(name)");
if (value==null)
throw new NullPointerException("XmlRpcSessionInfo.setObject(value)");
Object old_val = m_store.setObject(namespace,name,value);
if ( (value instanceof SessionValueBindListener)
|| ((old_val!=null) && (old_val instanceof SessionValueBindListener)))
{ // fire events indicating an object is being replaced and/or added
SessionValueBindEvent evt = new SessionValueBindEvent(this,namespace,name,value);
if ((old_val!=null) && (old_val instanceof SessionValueBindListener))
((SessionValueBindListener)old_val).valueReplaced(evt);
if (value instanceof SessionValueBindListener)
((SessionValueBindListener)value).valueAdded(evt);
} // end if
return old_val;
} // end setObject
/**
* Removes an object from this session's <CODE>ObjectStore</CODE>. If the object implements
* {@link com.silverwrist.dynamo.event.SessionValueBindListener SessionValueBindListener}, its
* {@link com.silverwrist.dynamo.event.SessionValueBindListener#valueRemoved(com.silverwrist.dynamo.event.SessionValueBindEvent) valueRemoved()}
* method will be called.
*
* @param namespace The namespace to interpret the name relative to.
* @param name The name of the object to be removed.
* @return The previous object that was set into the <CODE>ObjectStore</CODE> under this namespace and name, or
* <CODE>null</CODE> if there was no such object.
*/
public Object removeObject(String namespace, String name)
{
if (namespace==null)
throw new NullPointerException("XmlRpcSessionInfo.removeObject(namespace)");
if (name==null)
throw new NullPointerException("XmlRpcSessionInfo.removeObject(name)");
Object old_val = m_store.removeObject(namespace,name);
if ((old_val!=null) && (old_val instanceof SessionValueBindListener))
((SessionValueBindListener)old_val).valueRemoved(new SessionValueBindEvent(this,namespace,name));
return old_val;
} // end removeObject
/**
* Returns a collection of all object namespaces that have been set into this session's <CODE>ObjectStore</CODE>.
*
* @return A <CODE>java.util.Collection</CODE> containing <CODE>String</CODE> objects specifying all the
* object namespaces.
*/
public Collection getNamespaces()
{
return m_store.getNamespaces();
} // end getNamespaces
/**
* Returns a collection of all object names that have been set into this session's <CODE>ObjectStore</CODE>
* under a given namespace.
*
* @param namespace The namespace to look for names under.
* @return A <CODE>java.util.Collection</CODE> containing <CODE>String</CODE> objects specifying all the
* object names for this namespace.
*/
public Collection getNamesForNamespace(String namespace)
{
return m_store.getNamesForNamespace(namespace);
} // end getNamesForNamespace
/*--------------------------------------------------------------------------------
* Implementations from interface SessionInfo
*--------------------------------------------------------------------------------
*/
/**
* Returns a value indicating the type of this session. This will usually be the same as the type of the
* {@link com.silverwrist.dynamo.iface.Request Request} objects that work with this session object.
*
* @return The type of this request.
* @see com.silverwrist.dynamo.RequestType
* @see com.silverwrist.dynamo.iface.Request#getType()
*/
public RequestType getSessionType()
{
return RequestType.XMLRPC;
} // end getSessionType
/**
* Returns the unique identifier for this session.
*
* @return The unique identifier for this session.
*/
public String getID()
{
return m_id;
} // end getID
/**
* Returns the time at which this session was created. This is expressed in the same units as
* <CODE>System.currentTimeMillis()</CODE>.
*
* @return The time at which the session was created.
*/
public long getCreationTime()
{
return m_created;
} // end getCreationTime
/**
* Returns the time at which this session was last accessed. This is expressed in the same units as
* <CODE>System.currentTimeMillis()</CODE>.
*
* @return The time at which the session was last accessed.
*/
public long getLastAccessedTime()
{
return m_last_access;
} // end getLastAccessedTime
/**
* Specifies the time, in seconds, between client requests before the framework will invalidate this
* session. A negative value indicates the session should never timeout.
*
* @param interval An integer specifying the number of seconds.
*/
public void setMaxInactiveInterval(int interval)
{
m_max_inactive = interval;
} // end setMaxInactiveInterval
/**
* Returns the maximum time interval, in seconds, that the framework will keep this session open between
* client accesses. After this interval, the framework will invalidate the session. The maximum time
* interval can be set with the {@link #setMaxInactiveInterval(int) setMaxInactiveInterval} method. A negative
* value indicates the session should never timeout.
*
* @return An integer specifying the number of seconds this session remains open between client requests.
*/
public int getMaxInactiveInterval()
{
return m_max_inactive;
} // end getMaxInactiveInterval
/**
* Causes the session to be invalidated, and any objects bound to it to be unbound. Also invalidates
* any underlying session attributes in the enclosing environment (such as the servlet container), if
* present.
*/
public void invalidate()
{
m_appcon.removeSessionLink(this);
m_subsystem.zapSession(m_id);
destroy();
} // end invalidate
/**
* Causes the session to be invalidated, and any objects bound to it to be unbound. If there are any
* underlying session attributes in the enclosing environment (such as the servlet container), they are
* unaffected.
*/
public void detach()
{
this.invalidate();
} // end detach
/*--------------------------------------------------------------------------------
* Implementations from interface ComponentShutdown
*--------------------------------------------------------------------------------
*/
/**
* Shuts down the session. It sends out session-exiting notifications, unbinds all variables from the
* session, and erases the contents.
*/
public void shutdown()
{
destroy();
} // end shutdown
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
/**
* Updates the "last accessed" time for this session to the current time.
*/
synchronized void touch()
{
m_last_access = System.currentTimeMillis();
} // end touch
/**
* Returns whether or not this session has expired and should be removed.
*
* @param time_tick A current time stamp value.
* @return <CODE>true</CODE> if the session has expired, <CODE>false</CODE> if not.
*/
synchronized boolean isExpired(long time_tick)
{
if (m_max_inactive<0)
return false; // never expire
else
return (time_tick - m_last_access) > (m_max_inactive * 1000L);
} // end isExpired
/**
* Sends out all session-initialized notifications. This is done as a separate operation because of the need
* to provide a {@link com.silverwrist.dynamo.iface.Request Request} context to send the event out in.
*
* @param r The <CODE>Request</CODE> to provide context for the events.
*/
void newSession(Request r)
{
logger.info("Calling sessionInitialized notifications on session " + m_id);
// Send the start-session notifications.
SessionInfoListener[] listeners = m_appcon.getSessionListeners();
if (listeners.length>0)
{ // call each listener in turn
SessionEventRequest req = new SessionEventRequest(this,true,r);
SessionInfoEvent evt = new SessionInfoEvent(req,this);
for (int i=0; i<listeners.length; i++)
listeners[i].sessionInitialized(evt);
} // end if
m_appcon.addSessionLink(this); // set it up to be zapped with the other sessions
} // end newSession
} // end class XmlRpcSessionInfo
@@ -0,0 +1,790 @@
/*
* 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-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.xmlrpc;
import java.util.*;
import org.apache.commons.lang.CharSet;
import org.apache.commons.lang.CharSetUtils;
import org.apache.log4j.Logger;
import org.w3c.dom.*;
import com.silverwrist.util.xml.*;
import com.silverwrist.dynamo.Namespaces;
import com.silverwrist.dynamo.app.ApplicationContainer;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.util.*;
public class XmlRpcSubSystem
implements NamedObject, ComponentInitialize, ComponentShutdown, XmlRpcCreateSession, XmlRpcConfiguration
{
/*--------------------------------------------------------------------------------
* Internal class implementing background sweep
*--------------------------------------------------------------------------------
*/
private class SessionSweeper implements BackgroundTask
{
/*====================================================================
* Constructor
*====================================================================
*/
SessionSweeper()
{ // do nothing
} // end constructor
/*====================================================================
* Implementations from interface BackgroundTask
*====================================================================
*/
public void run(ServiceProvider services)
{
LinkedList dead_sessions = new LinkedList();
long timer_tick = System.currentTimeMillis();
synchronized (m_sessions)
{ // loop over the session list and add things to it
Iterator it = m_sessions.values().iterator();
while (it.hasNext())
{ // get each session and test its expiration status
XmlRpcSessionInfo session = (XmlRpcSessionInfo)(it.next());
if (session.isExpired(timer_tick))
dead_sessions.addLast(session);
} // end while
} // end synchronizedBlock
while (!(dead_sessions.isEmpty()))
{ // invalidate all the dead sessions
XmlRpcSessionInfo session = (XmlRpcSessionInfo)(dead_sessions.removeFirst());
session.invalidate();
} // end while
} // end run
} // end class SessionSweeper
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static Logger logger = Logger.getLogger(XmlRpcSubSystem.class);
private static final long SWEEP_INTERVAL = 60000L; // every minute
private static final int DEFAULT_MAX_AGE = 3600; // last for one hour
private static final String[] METHOD_CHARS = { "A-Z", "a-z", "0-9", "_.:/" };
private static final CharSet s_method_chars;
private static final String PREFIX = "xmlrpcsess:";
private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
private static final int ID_LENGTH = 40;
private static Random rng = new Random(); // random number generator
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private ApplicationContainer m_appcon = null; // application container
private LinkedList m_shutdown_list = new LinkedList(); // objects to be shut down
private String m_name; // name of this object
private Capabilities m_capas = new Capabilities(); // capabilities manager
private int m_default_maxage = DEFAULT_MAX_AGE; // default maximum age of sessions
private Hashtable m_sessions = new Hashtable(); // sessions we manage
private ArrayList m_internal_disp = new ArrayList(); // internal dispatchers
private Vector m_installed_disp = new Vector(); // dispatchers installed via the API
private ArrayList m_config_disp = new ArrayList(); // dispatchers configured via the config data
private ArrayList m_internal_fmap = new ArrayList(); // internal fault mappers
private Vector m_installed_fmap = new Vector(); // fault mappers installed via the API
private ArrayList m_config_fmap = new ArrayList(); // fault mappers configured via the config data
private ComponentShutdown m_init_hook; // initialization services hook
private ComponentShutdown m_sweep_task; // sweep task
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public XmlRpcSubSystem()
{
try
{ // Add internal dispatchers to the first list
m_internal_disp.add(new RegisteredDispatcher("system\\.getCapabilities",m_capas));
m_internal_disp.add(new RegisteredDispatcher("system\\.multicall",new MultiCallDispatcher(this)));
IntrospectionDispatcher id = new IntrospectionDispatcher(this);
m_internal_disp.add(new RegisteredDispatcher("system\\.listMethods",id));
m_internal_disp.add(new RegisteredDispatcher("system\\.methodSignature",id));
m_internal_disp.add(new RegisteredDispatcher("system\\.methodHelp",id));
} // end try
catch (ConfigException e)
{ // this shouldn't happen....
logger.fatal("ACK! internal dispatcher add failed!",e);
} // end catch
} // end constructor
/*--------------------------------------------------------------------------------
* Internal operations
*--------------------------------------------------------------------------------
*/
private static final ComponentInitialize getComponentInitialize(Object obj)
{
if (obj instanceof ComponentInitialize)
return (ComponentInitialize)obj;
if (obj instanceof ServiceProvider)
{ // it may be a service provider interface
try
{ // look for ComponentInitialize as a service
ServiceProvider sp = (ServiceProvider)obj;
ComponentInitialize rc = (ComponentInitialize)(sp.queryService(ComponentInitialize.class));
return rc;
} // end try
catch (NoSuchServiceException e)
{ // do nothing here
} // end catch
} // end if
return null; // no dice!
} // end getComponentInitialize
private static final ComponentShutdown getComponentShutdown(Object obj)
{
if (obj instanceof ComponentShutdown)
return (ComponentShutdown)obj;
if (obj instanceof ServiceProvider)
{ // it may be a service provider interface
try
{ // look for ComponentShutdown as a service
ServiceProvider sp = (ServiceProvider)obj;
ComponentShutdown rc = (ComponentShutdown)(sp.queryService(ComponentShutdown.class));
return rc;
} // end try
catch (NoSuchServiceException e)
{ // do nothing here
} // end catch
} // end if
return null; // no dice!
} // end getComponentShutdown
private static final boolean isValidMethodName(String name)
{
if ((name==null) || (name.length()==0))
return false;
for (int i=0; i<name.length(); i++)
{ // test each character in turn
if (!(s_method_chars.contains(name.charAt(i))))
return false; // found a bogus character
} // end for
return true; // all tests passed - ship it!
} // end isValidMethodName
private static final XmlRpcDispatcher scanDispatcherList(List l, String method_name)
{
Iterator it = l.iterator();
while (it.hasNext())
{ // locate a dispatcher by matching the method name
RegisteredDispatcher disp = (RegisteredDispatcher)(it.next());
if (disp.match(method_name))
return disp.getDispatcher();
} // end while
return null;
} // end scanDispatcherList
private static final void copyDispatchers(Set dest, List source)
{
Iterator it = source.iterator();
while (it.hasNext())
{ // strip out all dispatchers and return them
RegisteredDispatcher disp = (RegisteredDispatcher)(it.next());
dest.add(disp.getDispatcher());
} // end while
} // end copyDispatchers
private static final XmlRpcFaultMapper scanFaultMapperList(List l, Class klass)
{
Iterator it = l.iterator();
while (it.hasNext())
{ // locate a fault mapper by matching the class
RegisteredFaultMapper fmap = (RegisteredFaultMapper)(it.next());
if (fmap.match(klass))
return fmap.getFaultMapper();
} // end while
return null;
} // end scanFaultMapperList
private static final String generateID()
{
StringBuffer buf = new StringBuffer(PREFIX);
for (int i=0; i<ID_LENGTH; i++)
buf.append(ALPHABET.charAt(rng.nextInt(ALPHABET.length())));
return buf.toString();
} // end generateID
private final XmlRpcDispatcher createDispatcherObject(Element config_root, ServiceProvider services)
throws ConfigException
{
XMLLoader loader = XMLLoader.get();
String klassname = null;
try
{ // get the classname and load it, and create an object
klassname = loader.getAttribute(config_root,"classname");
if (logger.isDebugEnabled())
logger.debug("createDispatcherObject: Creating new XmlRpcDispatcher of class " + klassname);
Class klass = Class.forName(klassname);
if (!(XmlRpcDispatcher.class.isAssignableFrom(klass)))
{ // this object is not a valid XmlRpcDispatcher
logger.error("object " + klassname + " does not implement XmlRpcDispatcher");
ConfigException ce = new ConfigException(XmlRpcSubSystem.class,"XmlRpcMessages","xdisp.notXD");
ce.setParameter(0,klassname);
throw ce;
} // end if
// instantiate the object, and initialize it as needed
Object rc = klass.newInstance();
ComponentInitialize init = getComponentInitialize(rc);
if (init!=null)
init.initialize(config_root,services);
synchronized (this)
{ // save its shutdown hook for later
ComponentShutdown sd = getComponentShutdown(rc);
if (sd!=null)
m_shutdown_list.addFirst(sd);
} // end synchronized block
if (logger.isDebugEnabled())
logger.debug("XML-RPC dispatcher (of class " + klassname + ") created");
return (XmlRpcDispatcher)rc;
} // end try
catch (XMLLoadException e)
{ // error getting class name - throw the ConfigException
logger.error("XML loader failure",e);
throw new ConfigException(e);
} // end catch
catch (ClassNotFoundException e)
{ // the class was not found
ConfigException ce = new ConfigException(XmlRpcSubSystem.class,"XmlRpcMessages","xdisp.classNotFound");
ce.setParameter(0,klassname);
throw ce;
} // end catch
catch (IllegalAccessException e)
{ // unable to create this object
ConfigException ce = new ConfigException(XmlRpcSubSystem.class,"XmlRpcMessages","xdisp.createError");
ce.setParameter(0,klassname);
throw ce;
} // end catch
catch (InstantiationException e)
{ // unable to create this object
ConfigException ce = new ConfigException(XmlRpcSubSystem.class,"XmlRpcMessages","xdisp.createError");
ce.setParameter(0,klassname);
throw ce;
} // end catch
} // end createDispatcherObject
private final XmlRpcFaultMapper createFaultMapperObject(Element config_root, ServiceProvider services)
throws ConfigException
{
XMLLoader loader = XMLLoader.get();
String klassname = null;
try
{ // get the classname and load it, and create an object
klassname = loader.getAttribute(config_root,"classname");
if (logger.isDebugEnabled())
logger.debug("createFaultMapperObject: Creating new XmlRpcFaultMapper of class " + klassname);
Class klass = Class.forName(klassname);
if (!(XmlRpcFaultMapper.class.isAssignableFrom(klass)))
{ // this object is not a valid XmlRpcFaultMapper
logger.error("object " + klassname + " does not implement XmlRpcFaultMapper");
ConfigException ce = new ConfigException(XmlRpcSubSystem.class,"XmlRpcMessages","xfmap.notXFM");
ce.setParameter(0,klassname);
throw ce;
} // end if
// instantiate the object, and initialize it as needed
Object rc = klass.newInstance();
ComponentInitialize init = getComponentInitialize(rc);
if (init!=null)
init.initialize(config_root,services);
synchronized (this)
{ // save its shutdown hook for later
ComponentShutdown sd = getComponentShutdown(rc);
if (sd!=null)
m_shutdown_list.addFirst(sd);
} // end synchronized block
if (logger.isDebugEnabled())
logger.debug("XML-RPC fault mapper (of class " + klassname + ") created");
return (XmlRpcFaultMapper)rc;
} // end try
catch (XMLLoadException e)
{ // error getting class name - throw the ConfigException
logger.error("XML loader failure",e);
throw new ConfigException(e);
} // end catch
catch (ClassNotFoundException e)
{ // the class was not found
ConfigException ce = new ConfigException(XmlRpcSubSystem.class,"XmlRpcMessages","xfmap.classNotFound");
ce.setParameter(0,klassname);
throw ce;
} // end catch
catch (IllegalAccessException e)
{ // unable to create this object
ConfigException ce = new ConfigException(XmlRpcSubSystem.class,"XmlRpcMessages","xfmap.createError");
ce.setParameter(0,klassname);
throw ce;
} // end catch
catch (InstantiationException e)
{ // unable to create this object
ConfigException ce = new ConfigException(XmlRpcSubSystem.class,"XmlRpcMessages","xfmap.createError");
ce.setParameter(0,klassname);
throw ce;
} // end catch
} // end createFaultMapperObject
private final SessionInfo lookupSession(String id, Request r)
{
XmlRpcSessionInfo rc = null;
boolean is_new = false;
synchronized (m_sessions)
{ // look up a session...
rc = (XmlRpcSessionInfo)(m_sessions.get(id));
if (rc==null)
{ // not present - add it with this ID, which must have been valid at one point
rc = new XmlRpcSessionInfo(this,m_appcon,id);
m_sessions.put(id,rc);
is_new = true;
} // end if
} // end synchronized block
if (is_new)
rc.newSession(r); // yay! new session!
else
rc.touch(); // update last access time
return rc;
} // end lookupSession
private final Object execDispatcher(XmlRpcDispatcher disp, Request r, Application app)
throws Exception, FaultCode
{
Request my_req = r;
String session_id = disp.getSessionIDParamValue(r,app);
if (session_id!=null)
{ // get the session and "tack it" onto the request
SessionInfo session = lookupSession(session_id,r);
if (session!=null)
my_req = new ReplaceSessionRequest(r,session);
} // end if
return disp.dispatchXmlRpcCall(my_req,app);
} // end execDispatcher
/*--------------------------------------------------------------------------------
* Implementations from interface NamedObject
*--------------------------------------------------------------------------------
*/
/**
* Returns the name of this object.
*
* @return The name of this object.
*/
public String getName()
{
return m_name;
} // end getName
/*--------------------------------------------------------------------------------
* Implementations from interface ComponentInitialize
*--------------------------------------------------------------------------------
*/
/**
* Initialize the XML-RPC subsystem.
*
* @param config_root Pointer to the section of the Dynamo XML configuration file that configures this
* particular component. This is to be considered "read-only" by the component.
* @param services An implementation of {@link com.silverwrist.dynamo.iface.ServiceProvider ServiceProvider}
* which provides initialization services to the component. This will include an implementation
* of {@link com.silverwrist.dynamo.iface.ObjectProvider ObjectProvider} which may be used to
* get information about other objects previously initialized by the application.
* @exception com.silverwrist.dynamo.except.ConfigException If an error is encountered in the component
* configuration.
*/
public void initialize(Element config_root, ServiceProvider services) throws ConfigException
{
XMLLoader loader = XMLLoader.get();
try
{ // verify the right node name
loader.verifyNodeName(config_root,"object");
// get the object's name
m_name = loader.getAttribute(config_root,"name");
// get the default maximum age
m_default_maxage = loader.getAttributeInt(config_root,"maxAge",DEFAULT_MAX_AGE);
// load up a list of all dispatch objects to be initialized
List l = loader.getMatchingSubElements(config_root,"dispatch");
Iterator it = l.iterator();
while (it.hasNext())
{ // load each dispatch object in turn
Element d_elt = (Element)(it.next());
String method_name = loader.getAttribute(d_elt,"method");
XmlRpcDispatcher disp_obj = createDispatcherObject(d_elt,services);
m_config_disp.add(new RegisteredDispatcher(method_name,disp_obj));
} // end while
// load up the list of all fault mapper objects to be initialized
l = loader.getMatchingSubElements(config_root,"fault-mapper");
it = l.iterator();
while (it.hasNext())
{ // load each fault mapper object in turn
Element fm_elt = (Element)(it.next());
String klassname = loader.getAttribute(fm_elt,"for");
Class klass = null;
try
{ // get the class for which this will translate
klass = Class.forName(klassname);
if (!(Exception.class.isAssignableFrom(klass)))
{ // it's not an Exception - we can't have that
ConfigException ce = new ConfigException(XmlRpcSubSystem.class,"XmlRpcMessages",
"xfmap.badExceptClass");
ce.setParameter(0,klassname);
throw ce;
} // end if
} // end try
catch (ClassNotFoundException e)
{ // class was not found
ConfigException ce = new ConfigException(XmlRpcSubSystem.class,"XmlRpcMessages",
"xfmap.noExceptClass");
ce.setParameter(0,klassname);
throw ce;
} // end catch
XmlRpcFaultMapper fm_obj = createFaultMapperObject(fm_elt,services);
m_config_fmap.add(new RegisteredFaultMapper(klass,fm_obj));
} // end while
// load up the list of all capabilities to be added
l = loader.getMatchingSubElements(config_root,"capability");
it = l.iterator();
while (it.hasNext())
{ // get each capability in turn and push it in
Element capa_elt = (Element)(it.next());
String name = loader.getAttribute(capa_elt,"name");
String url = loader.getAttribute(capa_elt,"url");
int version = loader.getAttributeInt(capa_elt,"version");
m_capas.insertCapability(name,url,version);
} // end while
} // end try
catch (XMLLoadException e)
{ // error loading XML config data
throw new ConfigException(e);
} // end catch
// Get the application container.
ObjectProvider op = (ObjectProvider)(services.queryService(ObjectProvider.class));
m_appcon = (ApplicationContainer)(op.getObject(Namespaces.DYNAMO_APPLICATION_NAMESPACE,"__container__"));
// Add the XmlRpcConfiguration service to Dynamo's init services.
HookServiceProviders hooker = (HookServiceProviders)(services.queryService(HookServiceProviders.class));
SingletonServiceProvider ssp = new SingletonServiceProvider("XmlRpcSubSystem",XmlRpcConfiguration.class,
(XmlRpcConfiguration)this);
m_init_hook = hooker.hookInitServiceProvider(ssp);
// Set up the sweeper to run at a fixed rate.
BackgroundScheduler sched = (BackgroundScheduler)(services.queryService(BackgroundScheduler.class));
m_sweep_task = sched.runTaskFixedRate(new SessionSweeper(),SWEEP_INTERVAL,SWEEP_INTERVAL);
} // end initialize
/*--------------------------------------------------------------------------------
* Implementations from interface ComponentShutdown
*--------------------------------------------------------------------------------
*/
/**
* Shuts down the XML-RPC subsystem.
*/
public void shutdown()
{
m_sweep_task.shutdown(); // shut down the sweep task
m_sweep_task = null;
m_init_hook.shutdown(); // shut down the initialization hook
m_init_hook = null;
if (logger.isDebugEnabled())
logger.debug("XmlRpcSubSystem.shutdown(): " + m_shutdown_list.size() + " objects to blow away");
while (m_shutdown_list.size()>0)
{ // shut down all components in reverse order of creation
ComponentShutdown sd = (ComponentShutdown)(m_shutdown_list.removeFirst());
sd.shutdown();
} // end while
m_sessions.clear(); // sessions already shut down by application container
m_internal_disp.clear();
m_installed_disp.clear();
m_config_disp.clear();
m_appcon = null;
} // end shutdown
/*--------------------------------------------------------------------------------
* Implementations from interface XmlRpcCreateSession
*--------------------------------------------------------------------------------
*/
public SessionInfo createNewSession(Request r)
{
XmlRpcSessionInfo rc = null;
synchronized (m_sessions)
{ // generate a new session ID and add it to the table
String new_id = generateID();
while (m_sessions.containsKey(new_id))
new_id = generateID();
rc = new XmlRpcSessionInfo(this,m_appcon,new_id);
m_sessions.put(new_id,rc);
} // end synchronized block
rc.newSession(r); // initiate me!
return rc;
} // end createNewSession
/*--------------------------------------------------------------------------------
* Implementations from interface XmlRpcConfiguration
*--------------------------------------------------------------------------------
*/
public ComponentShutdown addDispatcher(String method, XmlRpcDispatcher disp) throws ConfigException
{
RegisteredDispatcher rd = new RegisteredDispatcher(method,disp);
m_installed_disp.add(rd);
return new ShutdownVectorRemove(m_installed_disp,rd);
} // end addDispatcher
public ComponentShutdown addFaultMapper(Class klass, XmlRpcFaultMapper fmap) throws ConfigException
{
RegisteredFaultMapper rfm = new RegisteredFaultMapper(klass,fmap);
m_installed_fmap.add(rfm);
return new ShutdownVectorRemove(m_installed_fmap,rfm);
} // end addFaultMapper
public ComponentShutdown addCapability(String name, String url, int version)
{
return m_capas.addCapability(name,url,version);
} // end addCapability
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
/**
* Returns the default maximum inactive interval for XML-RPC sessions, in seconds.
*
* @return The default maximum inactive interval for XML-RPC sessions, in seconds.
*/
int getDefaultMaxAge()
{
return m_default_maxage;
} // end getDefaultMaxAge
/**
* Removes a session from the list of sessions we manage.
*
* @param id ID of the session to be removed.
*/
void zapSession(String id)
{
m_sessions.remove(id);
} // end zapSession
XmlRpcDispatcher getDispatcher(String method_name)
{
XmlRpcDispatcher disp = scanDispatcherList(m_internal_disp,method_name);
if (disp==null)
disp = scanDispatcherList(m_installed_disp,method_name);
if (disp==null)
disp = scanDispatcherList(m_config_disp,method_name);
return disp;
} // end getDispatcher
Set getAllDispatchers()
{
HashSet rc = new HashSet();
copyDispatchers(rc,m_internal_disp);
copyDispatchers(rc,m_installed_disp);
copyDispatchers(rc,m_config_disp);
return rc;
} // end getAllDispatchers
Object dispatch(Request r, Application app) throws Exception, FaultCode
{
// Get method name and make sure it's valid.
String method_name = r.getQueryString();
if (!isValidMethodName(method_name))
throw new SystemFaultCode(SystemFaultCode.METHOD_NOT_FOUND,"Invalid method name: " + method_name);
// Look for the appropriate dispatcher object.
XmlRpcDispatcher disp = getDispatcher(method_name);
if (disp==null) // dispatcher not found!
throw new XmlRpcMethodNotFound(method_name);
// Execute the dispatcher!
return execDispatcher(disp,r,app);
} // end dispatch
FaultCode translateException(Request r, Exception e)
{
Class klass = e.getClass();
int code = 0;
do
{ // scan upwards through the list of fault mappers and through class hierarchy
XmlRpcFaultMapper fmap = scanFaultMapperList(m_internal_fmap,klass);
if (fmap!=null)
{ // try the fault mapper
code = fmap.getXmlRpcFaultCodeForException(r,e);
if (code!=0)
break;
else
fmap = null;
} // end if
if (fmap==null)
fmap = scanFaultMapperList(m_installed_fmap,klass);
if (fmap!=null)
{ // try the fault mapper
code = fmap.getXmlRpcFaultCodeForException(r,e);
if (code!=0)
break;
else
fmap = null;
} // end if
if (fmap==null)
fmap = scanFaultMapperList(m_config_fmap,klass);
if (fmap!=null)
{ // try the fault mapper
code = fmap.getXmlRpcFaultCodeForException(r,e);
if (code!=0)
break;
else
fmap = null;
} // end if
if (fmap==null)
klass = klass.getSuperclass(); // try the superclass and see if that gets us anywhere
} while (klass!=Throwable.class); // end do
return new FaultCode(code,e);
} // end translateException
/*--------------------------------------------------------------------------------
* Static initializer
*--------------------------------------------------------------------------------
*/
static
{ // evaluate the character set
s_method_chars = CharSetUtils.evaluateSet(METHOD_CHARS);
} // end static initializer
} // end class XmlRpcSubSystem
@@ -0,0 +1,38 @@
/*
* 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-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.xmlrpc;
public interface XmlRpcTypeNames
{
public static final String TYPE_INT = "number";
public static final String TYPE_BOOLEAN = "boolean";
public static final String TYPE_STRING = "string";
public static final String TYPE_DOUBLE = "double";
public static final String TYPE_DATETIME = "dateTime";
public static final String TYPE_BASE64 = "base64";
public static final String TYPE_STRUCT = "struct";
public static final String TYPE_ARRAY = "array";
} // end interface XmlRpcTypeNames