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 = "&gt;";
           protected static final String AMPERSAND_ENTITY = "&amp;";
   
  -        /**
  -         * 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");
           }
  
  
  


Reply via email to