moved the serialization and deserialization of XML-RPC values into its own

class, 'cos we're going to write a client implementation eventually, and
it can share this code
This commit is contained in:
Eric J. Bowersox 2003-07-16 21:25:00 +00:00
parent 1762784ef0
commit 2eb1f58dba
3 changed files with 873 additions and 849 deletions

View File

@ -20,12 +20,9 @@ package com.silverwrist.dynamo.xmlrpc;
import java.io.*; import java.io.*;
import java.text.*; import java.text.*;
import java.util.*; import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.servlet.*; import javax.servlet.*;
import javax.servlet.http.*; import javax.servlet.http.*;
import org.w3c.dom.*; import org.w3c.dom.*;
import com.silverwrist.util.*;
import com.silverwrist.util.xml.*; import com.silverwrist.util.xml.*;
import com.silverwrist.dynamo.RequestType; import com.silverwrist.dynamo.RequestType;
import com.silverwrist.dynamo.Verb; import com.silverwrist.dynamo.Verb;
@ -42,27 +39,6 @@ import com.silverwrist.dynamo.util.*;
*/ */
class XmlRpcRequest extends BaseDelegatingServiceProvider implements Request 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 * Attributes
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
@ -120,6 +96,7 @@ class XmlRpcRequest extends BaseDelegatingServiceProvider implements Request
} // end catch } // end catch
XmlRpcSerializer serializer = XmlRpcSerializer.get();
try try
{ // load the XML body of the request, get the method name and parameters { // load the XML body of the request, get the method name and parameters
Element method_call = loader.getRootElement(request_doc,"methodCall"); Element method_call = loader.getRootElement(request_doc,"methodCall");
@ -135,7 +112,7 @@ class XmlRpcRequest extends BaseDelegatingServiceProvider implements Request
{ // get the <value/> subelement from each <param/> and store it { // get the <value/> subelement from each <param/> and store it
Element elt = (Element)(it.next()); Element elt = (Element)(it.next());
Element value_elt = loader.getSubElement(elt,"value"); Element value_elt = loader.getSubElement(elt,"value");
m_params.put(String.valueOf(ndx++),parseValue(value_elt)); m_params.put(String.valueOf(ndx++),serializer.deserialize(value_elt));
} // end while } // end while
@ -155,274 +132,6 @@ class XmlRpcRequest extends BaseDelegatingServiceProvider implements Request
} // end constructor } // 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 * Implementations from interface ObjectProvider
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
@ -670,31 +379,4 @@ class XmlRpcRequest extends BaseDelegatingServiceProvider implements Request
} // end getLocales } // 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 } // end class XmlRpcRequest

View File

@ -11,40 +11,19 @@
* *
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>, * 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 * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
* *
* Contributor(s): * Contributor(s):
*/ */
package com.silverwrist.dynamo.xmlrpc; package com.silverwrist.dynamo.xmlrpc;
import java.io.*; 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.HttpStatusCode;
import com.silverwrist.dynamo.except.*; import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*; import com.silverwrist.dynamo.iface.*;
public class XmlRpcResult implements SelfRenderable, XmlRpcSelfSerializing 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 * Attributes
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
@ -73,7 +52,7 @@ public class XmlRpcResult implements SelfRenderable, XmlRpcSelfSerializing
// Serialize the output value to a StringWriter. // Serialize the output value to a StringWriter.
StringWriter wr = new StringWriter(); StringWriter wr = new StringWriter();
wr.write("<methodResponse><params><param>\r\n<value>"); wr.write("<methodResponse><params><param>\r\n<value>");
serialize(wr,m_obj); XmlRpcSerializer.get().serialize(wr,m_obj);
wr.write("</value>\r\n</param></params></methodResponse>\r\n"); wr.write("</value>\r\n</param></params></methodResponse>\r\n");
// Now render the binary equivalent of this structure. // Now render the binary equivalent of this structure.
@ -107,513 +86,8 @@ public class XmlRpcResult implements SelfRenderable, XmlRpcSelfSerializing
public void serializeXmlRpc(Writer wr) throws IOException public void serializeXmlRpc(Writer wr) throws IOException
{ {
serialize(wr,m_obj); XmlRpcSerializer.get().serialize(wr,m_obj);
} // end serializeXmlRpc } // 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 } // end class XmlRpcResult

View File

@ -0,0 +1,868 @@
/*
* 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) 2003 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 org.w3c.dom.*;
import com.silverwrist.util.*;
import com.silverwrist.util.xml.*;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
public class XmlRpcSerializer
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static XmlRpcSerializer _self = null;
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";
// 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 String EMPTY_STRING = "";
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private final DateFormat m_iso8601; // the ISO 8601 date format
private final Map m_type_map; // mapping of type values to indices
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
private XmlRpcSerializer()
{
// Initialize the ISO 8601 date formatter.
SimpleDateFormat iso = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
iso.setCalendar(new GregorianCalendar(new SimpleTimeZone(0,"UTC")));
m_iso8601 = iso;
// 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));
m_type_map = Collections.unmodifiableMap(tmp);
} // end constructor
/*--------------------------------------------------------------------------------
* Internal operations
*--------------------------------------------------------------------------------
*/
/**
* Deserializes 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 final Map deserializeStruct(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,deserialize(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 deserializeStruct
/**
* Deserializes 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 final List deserializeArray(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(deserialize(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 deserializeArray
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
public 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 void serialize(Writer wr, boolean b) throws IOException
{
wr.write("<boolean>");
wr.write(b ? "1" : "0");
wr.write("</boolean>");
} // end serialize
public 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 void serialize(Writer wr, byte b) throws IOException
{
serialize(wr,(int)b);
} // end serialize
public void serialize(Writer wr, byte[] b) throws IOException
{
serializeBinary(wr,new ByteArrayInputStream(b));
} // end serialize
public void serialize(Writer wr, char c) throws IOException
{
char[] xa = new char[] { c };
serializeString(wr,new String(xa));
} // end serialize
public 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 void serialize(Writer wr, short s) throws IOException
{
serialize(wr,(int)s);
} // end serialize
public 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 void serialize(Writer wr, int i) throws IOException
{
wr.write("<int>");
wr.write(String.valueOf(i));
wr.write("</int>");
} // end serialize
public 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 void serialize(Writer wr, long l) throws IOException
{
serialize(wr,(double)l);
} // end serialize
public 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 void serialize(Writer wr, float f) throws IOException
{
serialize(wr,(double)f);
} // end serialize
public 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 void serialize(Writer wr, double d) throws IOException
{
wr.write("<double>");
wr.write(String.valueOf(d));
wr.write("</double>");
} // end serialize
public 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 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 void serializeCollection(Writer wr, Collection coll) throws IOException
{
serializeIterator(wr,coll.iterator());
} // end serializeCollection
public void serializeDate(Writer wr, Date d) throws IOException
{
wr.write("<dateTime.iso8601>");
wr.write(m_iso8601.format(d));
wr.write("</dateTime.iso8601>");
} // end serializeDate
public 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 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 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 void serializeString(Writer wr, String s) throws IOException
{
wr.write("<string>");
wr.write(StringUtils.encodeHTML(s));
wr.write("</string>");
} // end serializeString
public 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 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
/**
* Deserializes 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.
*/
public Object deserialize(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)(m_type_map.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 = m_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 = deserializeStruct(type_spec);
break;
case ITYP_ARRAY:
rc = deserializeArray(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 deserialize
/*--------------------------------------------------------------------------------
* External static operations
*--------------------------------------------------------------------------------
*/
public static XmlRpcSerializer get()
{
if (_self==null)
_self = new XmlRpcSerializer();
return _self;
} // end get
} // end class XmlRpcSerializer