dlr 02/02/18 15:22:29
Modified: src/java/org/apache/xmlrpc XmlRpc.java XmlRpcClient.java
XmlRpcClientLite.java XmlRpcServer.java
Log:
The following XmlWriter changes were inspired by a suggestion by
Timothy Peierls <[EMAIL PROTECTED]>, and reviewed by Jon Stevens
<[EMAIL PROTECTED]>:
"In any event, why not have XmlWriter write directly to an
OutputStreamWriter that wraps a ByteArrayOutputStream (maybe itself
wrapped in a BufferedWriter)? This would eliminate the need for a
StringBuffer, which is one of the problem areas that Dan is worried
about." -- Tim
XmlRpc:
o Moved writeObject() into XmlWriter (a paritial impl. the
ObjectOutput interface).
o Made XmlWriter sub-class OutputStreamWriter (taking a OutputStream
instead of StringBuffer in the ctor), for a more stream-friendly API.
This did away with the strbuf and enc members (equivalents are already
encapsulated by OutputStreamWriter).
o Reduced visibility of XmlWriter's XML-tag writing methods from
public to protected (they're mostly called from writeObject() and
other classes w/in the org.apache.xmlrpc package).
o Removed write(char[]), write(String), toString(), and getBytes()
methods -- they're already implemented in some form by the
super-class. NOTE: flush() should be called before toByteArray() (the
replacement for the getBytes() method).
XmlRpcClient, XmlRpcClientLite, and XmlRpcServer:
o Traded strbuff StringBuffer member for buffer ByteArrayOutputStream
member.
o Took XmlWriter API changes into account.
Revision Changes Path
1.17 +128 -143 xml-rpc/src/java/org/apache/xmlrpc/XmlRpc.java
Index: XmlRpc.java
===================================================================
RCS file: /home/cvs/xml-rpc/src/java/org/apache/xmlrpc/XmlRpc.java,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -u -r1.16 -r1.17
--- XmlRpc.java 18 Feb 2002 17:06:15 -0000 1.16
+++ XmlRpc.java 18 Feb 2002 23:22:29 -0000 1.17
@@ -72,6 +72,7 @@
* @see XmlRpcClient
*
* @author <a href="mailto:[EMAIL PROTECTED]">Hannes Wallnoefer</a>
+ * @author <a href="mailto:[EMAIL PROTECTED]">Daniel Rall</a>
*/
public abstract class XmlRpc
extends HandlerBase
@@ -331,89 +332,6 @@
}
/**
- * Writes the XML representation of a supported Java object to
- * the XML writer.
- */
- void writeObject (Object what, XmlWriter writer)
- {
- writer.startElement ("value");
- if (what == null)
- {
- throw new RuntimeException ("null value not supported by XML-RPC");
- }
- else if (what instanceof String)
- {
- writer.chardata (what.toString ());
- }
- else if (what instanceof Integer)
- {
- writer.startElement ("int");
- writer.write (what.toString ());
- writer.endElement ("int");
- }
- else if (what instanceof Boolean)
- {
- writer.startElement ("boolean");
- writer.write (((Boolean) what).booleanValue () ? "1" : "0");
- writer.endElement ("boolean");
- }
- else if (what instanceof Double || what instanceof Float)
- {
- writer.startElement ("double");
- writer.write (what.toString ());
- writer.endElement ("double");
- }
- else if (what instanceof Date)
- {
- writer.startElement ("dateTime.iso8601");
- Date d = (Date) what;
- writer.write (dateformat.format (d));
- writer.endElement ("dateTime.iso8601");
- }
- else if (what instanceof byte[])
- {
- writer.startElement ("base64");
- writer.write (Base64.encode ((byte[]) what));
- writer.endElement ("base64");
- }
- else if (what instanceof Vector)
- {
- writer.startElement ("array");
- writer.startElement ("data");
- Vector v = (Vector) what;
- int l2 = v.size ();
- for (int i2 = 0; i2 < l2; i2++)
- writeObject (v.elementAt (i2), writer);
- writer.endElement ("data");
- writer.endElement ("array");
- }
- else if (what instanceof Hashtable)
- {
- writer.startElement ("struct");
- Hashtable h = (Hashtable) what;
- for (Enumeration e = h.keys (); e.hasMoreElements ();)
- {
- String nextkey = (String) e.nextElement ();
- Object nextval = h.get (nextkey);
- writer.startElement ("member");
- writer.startElement ("name");
- writer.write (nextkey);
- writer.endElement ("name");
- writeObject (nextval, writer);
- writer.endElement ("member");
- }
- writer.endElement ("struct");
- }
- else
- {
- throw new RuntimeException ("unsupported Java type: " +
- what.getClass ());
- }
- writer.endElement ("value");
- }
-
-
- /**
* This method is called when a root level object has been parsed.
*/
abstract void objectParsed (Object what);
@@ -700,9 +618,14 @@
/**
- * A quick and dirty XML writer.
+ * A quick and dirty XML writer. If you feed it a
+ * <code>ByteArrayInputStream</code>, it may be necessary to call
+ * <code>writer.flush()</code> before calling
+ * <code>buffer.toByteArray()</code> to get the data written to
+ * your byte buffer.
*/
class XmlWriter
+ extends OutputStreamWriter
{
protected static final String PROLOG_START =
"<?xml version=\"1.0\" encoding=\"";
@@ -713,55 +636,137 @@
protected static final String GREATER_THAN_ENTITY = ">";
protected static final String AMPERSAND_ENTITY = "&";
- /**
- * The buffer to write to.
- */
- StringBuffer buf;
-
- /**
- * The encoding to use.
- */
- String enc;
-
- public XmlWriter (StringBuffer buf)
+ public XmlWriter (OutputStream out)
+ throws UnsupportedEncodingException, IOException
{
// The default encoding used for XML-RPC is ISO-8859-1.
- this (buf, encoding);
+ this (out, encoding);
}
- public XmlWriter (StringBuffer buf, String enc)
+ public XmlWriter (OutputStream out, String enc)
+ throws UnsupportedEncodingException, IOException
{
- this.buf = buf;
- this.enc = enc;
+ super(out, enc);
// Add the XML prolog (which includes the encoding)
- buf.append (PROLOG_START);
- buf.append (encodings.getProperty (enc, enc));
- buf.append (PROLOG_END);
+ write(PROLOG_START);
+ write(encodings.getProperty(enc, enc));
+ write(PROLOG_END);
}
- public void startElement (String elem)
+ /**
+ * Writes the XML representation of a supported Java object
+ * type.
+ *
+ * @param obj The <code>Object</code> to write.
+ */
+ public void writeObject (Object obj)
+ throws IOException
{
- buf.append ('<');
- buf.append (elem);
- buf.append ('>');
+ startElement ("value");
+ if (obj == null)
+ {
+ throw new RuntimeException("null value not supported by XML-RPC");
+ }
+ else if (obj instanceof String)
+ {
+ chardata(obj.toString());
+ }
+ else if (obj instanceof Integer)
+ {
+ startElement("int");
+ write(obj.toString());
+ endElement("int");
+ }
+ else if (obj instanceof Boolean)
+ {
+ startElement("boolean");
+ write(((Boolean) obj).booleanValue() ? "1" : "0");
+ endElement("boolean");
+ }
+ else if (obj instanceof Double || obj instanceof Float)
+ {
+ startElement("double");
+ write(obj.toString());
+ endElement("double");
+ }
+ else if (obj instanceof Date)
+ {
+ startElement("dateTime.iso8601");
+ Date d = (Date) obj;
+ write(dateformat.format(d));
+ endElement("dateTime.iso8601");
+ }
+ else if (obj instanceof byte[])
+ {
+ startElement("base64");
+ write(Base64.encode((byte[]) obj));
+ endElement("base64");
+ }
+ else if (obj instanceof Vector)
+ {
+ startElement("array");
+ startElement("data");
+ Vector array = (Vector) obj;
+ int size = array.size();
+ for (int i = 0; i < size; i++)
+ {
+ writeObject(array.elementAt(i));
+ }
+ endElement("data");
+ endElement("array");
+ }
+ else if (obj instanceof Hashtable)
+ {
+ startElement("struct");
+ Hashtable struct = (Hashtable) obj;
+ for (Enumeration e = struct.keys(); e.hasMoreElements(); )
+ {
+ String nextkey = (String) e.nextElement();
+ Object nextval = struct.get(nextkey);
+ startElement("member");
+ startElement("name");
+ write(nextkey);
+ endElement("name");
+ writeObject(nextval);
+ endElement("member");
+ }
+ endElement("struct");
+ }
+ else
+ {
+ throw new RuntimeException("unsupported Java type: " +
+ obj.getClass());
+ }
+ endElement("value");
+ }
+
+ protected void startElement (String elem)
+ throws IOException
+ {
+ write('<');
+ write(elem);
+ write('>');
}
- public void endElement (String elem)
+ protected void endElement (String elem)
+ throws IOException
{
- buf.append (CLOSING_TAG_START);
- buf.append (elem);
- buf.append ('>');
+ write(CLOSING_TAG_START);
+ write(elem);
+ write('>');
}
- public void emptyElement (String elem)
+ protected void emptyElement (String elem)
+ throws IOException
{
- buf.append ('<');
- buf.append (elem);
- buf.append (SINGLE_TAG_END);
+ write('<');
+ write(elem);
+ write(SINGLE_TAG_END);
}
- public void chardata (String text)
+ protected void chardata (String text)
+ throws IOException
{
int l = text.length ();
for (int i = 0; i < l; i++)
@@ -769,39 +774,19 @@
char c = text.charAt (i);
switch (c)
{
- case '<' :
- buf.append (LESS_THAN_ENTITY);
+ case '<':
+ write(LESS_THAN_ENTITY);
break;
- case '>' :
- buf.append (GREATER_THAN_ENTITY);
+ case '>':
+ write(GREATER_THAN_ENTITY);
break;
- case '&' :
- buf.append (AMPERSAND_ENTITY);
+ case '&':
+ write(AMPERSAND_ENTITY);
break;
- default :
- buf.append (c);
+ default:
+ write(c);
}
}
- }
-
- public void write (char[] text)
- {
- buf.append (text);
- }
-
- public void write (String text)
- {
- buf.append (text);
- }
-
- public String toString ()
- {
- return buf.toString ();
- }
-
- public byte[] getBytes () throws UnsupportedEncodingException
- {
- return buf.toString ().getBytes (enc);
}
}
}
1.6 +20 -8 xml-rpc/src/java/org/apache/xmlrpc/XmlRpcClient.java
Index: XmlRpcClient.java
===================================================================
RCS file: /home/cvs/xml-rpc/src/java/org/apache/xmlrpc/XmlRpcClient.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -u -r1.5 -r1.6
--- XmlRpcClient.java 18 Feb 2002 17:06:15 -0000 1.5
+++ XmlRpcClient.java 18 Feb 2002 23:22:29 -0000 1.6
@@ -254,7 +254,11 @@
{
boolean fault;
Object result = null;
- StringBuffer strbuf;
+
+ /**
+ * The output buffer used in creating a request.
+ */
+ ByteArrayOutputStream buffer;
CallData call;
@@ -298,12 +302,15 @@
catch (Exception x)
{
if (callback != null)
+ {
try
{
callback.handleError (x, url, method);
}
catch (Exception ignore)
- {}
+ {
+ }
+ }
}
}
@@ -323,14 +330,19 @@
{
ByteArrayOutputStream bout = new ByteArrayOutputStream ();
- if (strbuf == null)
- strbuf = new StringBuffer ();
+ if (buffer == null)
+ {
+ buffer = new ByteArrayOutputStream();
+ }
else
- strbuf.setLength (0);
+ {
+ buffer.reset();
+ }
- XmlWriter writer = new XmlWriter (strbuf);
+ XmlWriter writer = new XmlWriter (buffer);
writeRequest (writer, method, params);
- byte[] request = writer.getBytes();
+ writer.flush();
+ byte[] request = buffer.toByteArray();
URLConnection con = url.openConnection ();
con.setDoInput (true);
@@ -407,7 +419,7 @@
for (int i = 0; i < l; i++)
{
writer.startElement ("param");
- writeObject (params.elementAt (i), writer);
+ writer.writeObject (params.elementAt (i));
writer.endElement ("param");
}
writer.endElement ("params");
1.3 +12 -9 xml-rpc/src/java/org/apache/xmlrpc/XmlRpcClientLite.java
Index: XmlRpcClientLite.java
===================================================================
RCS file: /home/cvs/xml-rpc/src/java/org/apache/xmlrpc/XmlRpcClientLite.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -u -r1.2 -r1.3
--- XmlRpcClientLite.java 18 Feb 2002 17:06:15 -0000 1.2
+++ XmlRpcClientLite.java 18 Feb 2002 23:22:29 -0000 1.3
@@ -126,7 +126,6 @@
class LiteWorker extends Worker implements Runnable
{
-
HttpClient client = null;
public LiteWorker ()
@@ -134,21 +133,25 @@
super ();
}
-
- Object execute (String method,
- Vector params) throws XmlRpcException, IOException
+ Object execute (String method, Vector params)
+ throws XmlRpcException, IOException
{
long now = System.currentTimeMillis ();
fault = false;
try
{
- if (strbuf == null)
- strbuf = new StringBuffer ();
+ if (buffer == null)
+ {
+ buffer = new ByteArrayOutputStream();
+ }
else
- strbuf.setLength (0);
- XmlWriter writer = new XmlWriter (strbuf);
+ {
+ buffer.reset();
+ }
+ XmlWriter writer = new XmlWriter (buffer);
writeRequest (writer, method, params);
- byte[] request = writer.getBytes();
+ writer.flush();
+ byte[] request = buffer.toByteArray();
// and send it to the server
if (client == null)
1.11 +68 -23 xml-rpc/src/java/org/apache/xmlrpc/XmlRpcServer.java
Index: XmlRpcServer.java
===================================================================
RCS file: /home/cvs/xml-rpc/src/java/org/apache/xmlrpc/XmlRpcServer.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -u -r1.10 -r1.11
--- XmlRpcServer.java 18 Feb 2002 17:06:15 -0000 1.10
+++ XmlRpcServer.java 18 Feb 2002 23:22:29 -0000 1.11
@@ -66,6 +66,7 @@
* HTTP listener, use the WebServer class instead.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Hannes Wallnoefer</a>
+ * @author <a href="mailto:[EMAIL PROTECTED]">Daniel Rall</a>
*/
public class XmlRpcServer
{
@@ -150,8 +151,9 @@
*/
class Worker extends XmlRpc
{
- Vector inParams;
- StringBuffer strbuf;
+ private Vector inParams;
+ private ByteArrayOutputStream buffer;
+ private XmlWriter writer;
/**
* Creates a new instance.
@@ -159,7 +161,7 @@
protected Worker()
{
inParams = new Vector();
- strbuf = new StringBuffer();
+ buffer = new ByteArrayOutputStream();
}
/**
@@ -175,7 +177,7 @@
finally
{
// Release most of our resources
- strbuf.setLength (0);
+ buffer.reset();
inParams.removeAllElements();
}
}
@@ -227,17 +229,22 @@
Object outParam;
if (handler instanceof AuthenticatedXmlRpcHandler)
+ {
outParam = ((AuthenticatedXmlRpcHandler) handler).
execute (methodName, inParams, user, password);
+ }
else
+ {
outParam = ((XmlRpcHandler) handler).execute (
methodName, inParams);
+ }
if (debug)
System.err.println ("outparam = "+outParam);
- XmlWriter writer = new XmlWriter (strbuf);
+ writer = new XmlWriter(buffer);
writeResponse (outParam, writer);
- result = writer.getBytes ();
+ writer.flush();
+ result = buffer.toByteArray();
}
catch (Exception x)
{
@@ -249,32 +256,69 @@
// It is possible that something is in the buffer
// if there were an exception during the writeResponse()
// call above.
- strbuf.setLength(0);
+ buffer.reset();
+
+ writer = null;
+ try
+ {
+ writer = new XmlWriter(buffer);
+ }
+ catch (UnsupportedEncodingException encx)
+ {
+ System.err.println("XmlRpcServer attempted to use " +
+ "unsupported encoding: " + encx);
+ // NOTE: If we weren't already using the default
+ // encoding, we could try it here.
+ }
+ catch (IOException iox)
+ {
+ System.err.println("XmlRpcServer experienced I/O error " +
+ "writing error response: " + iox);
+ }
- XmlWriter writer = new XmlWriter (strbuf);
String message = x.toString ();
- // check if XmlRpcException was thrown so we can get an error code
+ // Retrieve XmlRpcException error code (if possible).
int code = x instanceof XmlRpcException ?
((XmlRpcException) x).code : 0;
try
{
writeError (code, message, writer);
+ writer.flush();
}
- catch (XmlRpcException e)
+ catch (Exception e)
{
// Unlikely to occur, as we just sent a struct
// with an int and a string.
System.err.println("Unable to send error response to " +
"client: " + e);
}
- try
+
+ // If we were able to create a XmlWriter, we should
+ // have a response.
+ if (writer != null)
{
- result = writer.getBytes ();
+ result = buffer.toByteArray();
}
- catch (UnsupportedEncodingException encx)
+ else
+ {
+ result = "".getBytes();
+ }
+ }
+ finally
+ {
+ if (writer != null)
{
- System.err.println ("XmlRpcServer.execute: "+encx);
- result = writer.toString().getBytes();
+ try
+ {
+ writer.close();
+ }
+ catch (IOException iox)
+ {
+ // This is non-fatal, but worth logging a
+ // warning for.
+ System.err.println("Exception closing output stream: " +
+ iox);
+ }
}
}
if (debug)
@@ -284,8 +328,9 @@
}
/**
- * Called when an object to be added to the argument list has been parsed.
- */
+ * Called when an object to be added to the argument list has
+ * been parsed.
+ */
void objectParsed (Object what)
{
inParams.addElement (what);
@@ -294,14 +339,14 @@
/**
* Writes an XML-RPC response to the XML writer.
*/
- void writeResponse (Object param,
- XmlWriter writer) throws XmlRpcException
+ void writeResponse (Object param, XmlWriter writer)
+ throws XmlRpcException, IOException
{
writer.startElement ("methodResponse");
// if (param == null) param = ""; // workaround for Frontier bug
writer.startElement ("params");
writer.startElement ("param");
- writeObject (param, writer);
+ writer.writeObject (param);
writer.endElement ("param");
writer.endElement ("params");
writer.endElement ("methodResponse");
@@ -310,8 +355,8 @@
/**
* Writes an XML-RPC error response to the XML writer.
*/
- void writeError (int code, String message,
- XmlWriter writer) throws XmlRpcException
+ void writeError (int code, String message, XmlWriter writer)
+ throws XmlRpcException, IOException
{
// System.err.println ("error: "+message);
Hashtable h = new Hashtable ();
@@ -319,7 +364,7 @@
h.put ("faultString", message);
writer.startElement ("methodResponse");
writer.startElement ("fault");
- writeObject (h, writer);
+ writer.writeObject (h);
writer.endElement ("fault");
writer.endElement ("methodResponse");
}