You are viewing a plain text version of this content. The canonical link for it is here.
Posted to rpc-dev@xml.apache.org by ha...@apache.org on 2001/11/06 18:30:12 UTC

cvs commit: xml-rpc/src/java/org/apache/xmlrpc/applet JSXmlRpcApplet.java SimpleXmlRpcClient.java XmlRpcApplet.java XmlRpcException.java

hannes      01/11/06 09:30:12

  Added:       src/java/org/apache/xmlrpc/applet JSXmlRpcApplet.java
                        SimpleXmlRpcClient.java XmlRpcApplet.java
                        XmlRpcException.java
  Log:
  initial check-in of revised applet package
  
  Revision  Changes    Path
  1.1                  xml-rpc/src/java/org/apache/xmlrpc/applet/JSXmlRpcApplet.java
  
  Index: JSXmlRpcApplet.java
  ===================================================================
  package org.apache.xmlrpc.applet;
  
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "XML-RPC" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  
  import java.applet.*;
  import java.util.*;
  import java.net.MalformedURLException;
  
  
  /**
   * An applet that can be accessed via LiveConnect from JavaScript. It provides methods for adding
   * arguments and triggering method execution for XML-RPC requests. This works on recent Netscape
   * 4.x browsers as well as Internet Explorer 4.0 on Windows 95/NT, but not on IE/Mac. <p>
   *
   * Results from XML-RPC calls are exposed to JavaScript as the are, i.e. &lt;structs>s are
   * <a href=http://java.sun.com/products/jdk/1.1/docs/api/java.util.Hashtable.html>Hashtables</a>
   * and &lt;array>s are <a href=http://java.sun.com/products/jdk/1.1/docs/api/java.util.Vector.html>Vectors</a>
   * and can be accessed thru their public methods. It seems like Date objects are
   * not converted properly between JavaScript and Java, so the dateArg methods take long values instead of
   * Date objects as parameters (date.getTime()).
   */
  public class JSXmlRpcApplet extends XmlRpcApplet {
  
      public Object loaded = null;
  
      private String errorMessage;
      private Vector arguments;
  
      public void init () {
  	initClient ();
  	arguments = new Vector ();
  	loaded = Boolean.TRUE;
  	System.out.println ("JSXmlRpcApplet initialized");
      }
  
      // add ints (primitve != object) to structs, vectors
      public void addIntArg (int value) { arguments.addElement (new Integer (value)); }
      public void addIntArgToStruct (Hashtable struct, String key, int value) { struct.put (key, new Integer (value)); }
      public void addIntArgToArray (Vector ary, int value) { ary.addElement (new Integer (value)); }
  
      // add floats/doubles to structs, vectors
      public void addDoubleArg (float value) { arguments.addElement (new Double (value)); }
      public void addDoubleArgToStruct (Hashtable struct, String key, float value) { struct.put (key, new Double (value)); }
      public void addDoubleArgToArray (Vector ary, float value) { ary.addElement (new Double (value)); }
      public void addDoubleArg (double value) { arguments.addElement (new Double (value)); }
      public void addDoubleArgToStruct (Hashtable struct, String key, double value) { struct.put (key, new Double (value)); }
      public void addDoubleArgToArray (Vector ary, double value) { ary.addElement (new Double (value)); }
  
      // add bools to structs, vectors
      public void addBooleanArg (boolean value) { arguments.addElement (new Boolean (value)); }
      public void addBooleanArgToStruct (Hashtable struct, String key, boolean value) { struct.put (key, new Boolean(value)); }
      public void addBooleanArgToArray (Vector ary, boolean value) { ary.addElement (new Boolean(value)); }
  
      // add Dates to structs, vectors Date argument in SystemTimeMillis (seems to be the way)
      public void addDateArg (long dateNo) { arguments.addElement (new Date(dateNo)); }
      public void addDateArgToStruct (Hashtable struct, String key, long dateNo) { struct.put (key, new Date (dateNo)); }
      public void addDateArgToArray (Vector ary, long dateNo) { ary.addElement (new Date (dateNo)); }
  
      // add String arguments
      public void addStringArg (String str) { arguments.addElement (str); }
      public void addStringArgToStruct (Hashtable struct, String key, String str) { struct.put (key, str); }
      public void addStringArgToArray (Vector ary, String str) { ary.addElement (str); }
  
  
      // add Array arguments
      public Vector addArrayArg () {
  	Vector v = new Vector ();
  	arguments.addElement (v);
  	return v;
      }
      public Vector addArrayArgToStruct (Hashtable struct, String key) {
  	Vector v = new Vector ();
  	struct.put (key, v);
  	return v;
      }
      public Vector addArrayArgToArray (Vector ary) {
  	Vector v = new Vector ();
  	ary.addElement (v);
  	return v;
      }
  
  
      // add Struct arguments
      public Hashtable addStructArg () {
  	Hashtable ht = new Hashtable ();
  	arguments.addElement (ht);
  	return ht;
      }
      public Hashtable addStructArgToStruct (Hashtable struct, String key) {
  	Hashtable ht = new Hashtable ();
  	struct.put (key, ht);
  	return ht;
      }
      public Hashtable addStructArgToArray (Vector ary) {
  	Hashtable ht = new Hashtable ();
  	ary.addElement (ht);
  	return ht;
      }
  
      // get the errorMessage, null if none
      public String getErrorMessage() { return errorMessage; }
  
      public void reset () {
  	arguments = new Vector ();
      }
  
      public Object execute (String methodName) {
  	// XmlRpcSupport.setDebug (true);
  	errorMessage = null;
  	showStatus (Connecting to Server...");
  	Object returnValue = null;
  	try {
  	    returnValue = execute (methodName, arguments);
  	} catch (Exception e) {
  	    errorMessage = e.getMessage ();
  	    if (errorMessage == null || errorMessage == "")
  	        errorMessage = e.toString ();
  	}
  	// reset argument array for reuse
  	arguments = new Vector ();
  
  	showStatus ("");
  	return returnValue;
      }
  
  }
  
  
  
  1.1                  xml-rpc/src/java/org/apache/xmlrpc/applet/SimpleXmlRpcClient.java
  
  Index: SimpleXmlRpcClient.java
  ===================================================================
  package org.apache.xmlrpc.applet;
  
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "XML-RPC" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  
  import uk.co.wilson.xml.MinML;
  import org.xml.sax.*;
  import java.io.*;
  import java.util.*;
  import java.text.*;
  import java.net.*;
  
  
  /**
   *  A simple XML-RPC client 
   */
  
  public class SimpleXmlRpcClient {
  
      URL url;
     
      /** 
       * Construct a XML-RPC client with this URL.
       */
      public SimpleXmlRpcClient (URL url) {
  	this.url = url;
      }
  
      /** 
       * Construct a XML-RPC client for the URL represented by this String.
       */
      public SimpleXmlRpcClient (String url) throws MalformedURLException {
  	this.url = new URL (url);
      }
     
      /** 
       * Construct a XML-RPC client for the specified hostname and port.
       */
      public SimpleXmlRpcClient (String hostname, int port) throws MalformedURLException {
  	this.url = new URL ("http://"+hostname+":"+port+"/RPC2");
      }
  
      public Object execute (String method, Vector params) throws XmlRpcException, IOException {
      	return new XmlRpcSupport (url).execute (method, params);
      }
  
  }
  
  class XmlRpcSupport extends HandlerBase {
  
      URL url;
      String methodName;
      boolean fault = false;
      Object result = null;    
      
      // the stack we're parsing our values into.
      Stack values;
      Value currentValue;
  
      boolean readCdata;
  
      // formats for parsing and generating dateTime values
      static final DateFormat format = new SimpleDateFormat ("yyyyMMdd'T'HH:mm:ss");
      
      // used to collect character data of parameter values
      StringBuffer cdata = new StringBuffer ();
      
      // XML RPC parameter types used for dataMode
      static final int STRING = 0;
      static final int INTEGER = 1;
      static final int BOOLEAN = 2;
      static final int DOUBLE = 3;
      static final int DATE = 4;
      static final int BASE64 = 5;
      static final int STRUCT = 6;
      static final int ARRAY = 7;
  
      // for debugging output
      public static boolean debug = false;
      final static String types[] = {"String", "Integer", "Boolean", "Double", "Date", "Base64", "Struct", "Array"};
  
      
      public XmlRpcSupport (URL url) {
  	this.url = url;
      }
      
      
      /**
       * Switch debugging output on/off.
       */
      public static void setDebug (boolean val) {
  	debug = val;
      }
  
      /** 
       * Parse the input stream. For each root level object, method <code>objectParsed</code>
       * is called.
       */
      synchronized void parse (InputStream is) throws Exception {
  	values = new Stack ();
  	long now = System.currentTimeMillis ();
  	MinML parser =  new MinML ();
  	parser.setDocumentHandler (this);
  	parser.setErrorHandler (this);
  
  	parser.parse (new InputSource (is));
  
  	if (debug)
  	    System.out.println ("Spent "+(System.currentTimeMillis () - now)+" parsing");
      }
  
      /**
       * Writes the XML representation of a supported Java object to the XML writer.
       */
      void writeObject (Object what, XmlWriter writer) throws IOException {
  	writer.startElement ("value");
  	if (what instanceof String) {
      	    writer.write (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) {
  	    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 (format.format (d));
  	    writer.endElement ("dateTime.iso8601");
  	} else if (what instanceof byte[]) {
  	    writer.startElement ("base64");
  	    sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder ();
  	    writer.write (encoder.encodeBuffer ((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 {
  	    String unsupportedType = what == null ?
  	    	"null" :
  		what.getClass().toString ();
  	    throw new IOException ("unsupported Java type: " + unsupportedType);
  	}
  	writer.endElement ("value");
      }
  
  
      /**
       * Generate an XML-RPC request and send it to the server. Parse the result and
       * return the corresponding Java object.
       *
       * @exception XmlRpcException: If the remote host returned a fault message.
       * @exception IOException: If the call could not be made for lower level problems.
       */
      public Object execute (String method, Vector arguments) throws XmlRpcException, IOException {
  	fault = false;
  	long now = System.currentTimeMillis ();
      	try {
  	    StringBuffer strbuf = new StringBuffer ();
  	    XmlWriter writer = new XmlWriter (strbuf);
  	    writeRequest (writer, method, arguments);
  	    byte[] request = strbuf.toString().getBytes ();
  	    URLConnection con = url.openConnection ();
  	    con.setDoOutput (true);
  	    con.setDoInput (true);
  	    con.setUseCaches (false);
  	    con.setAllowUserInteraction(false);
  	    con.setRequestProperty ("Content-Length", Integer.toString (request.length));
  	    con.setRequestProperty ("Content-Type", "text/xml");
  	    // con.connect ();
  	    OutputStream out = con.getOutputStream ();
  	    out.write (request);
  	    out.flush ();
  	    InputStream in = con.getInputStream ();
  	    parse (in);
  	    System.out.println ("result = "+result);
  	} catch (Exception x) {
  	    x.printStackTrace ();
  	    throw new IOException (x.getMessage ());
  	}
  	if (fault) { // generate an XmlRpcException
  	    XmlRpcException exception = null;
  	    try {
  	        Hashtable f = (Hashtable) result;
  	        String faultString = (String) f.get ("faultString");
  	        int faultCode = Integer.parseInt (f.get ("faultCode").toString ());
  	        exception = new XmlRpcException (faultCode, faultString.trim ());
  	    } catch (Exception x) {
  	        throw new XmlRpcException (0, "Invalid fault response");
  	    }
  	    throw exception;
  	}
  	System.out.println ("Spent "+(System.currentTimeMillis () - now)+" in request");
  	return result;
      }
  
     
      /**
       * Called when the return value has been parsed. 
       */
      void objectParsed (Object what) {
  	result = what;
      }
      
      
      /**
       * Generate an XML-RPC request from a method name and a parameter vector.
       */
      void writeRequest (XmlWriter writer, String method, Vector params) throws IOException {
  	writer.startElement ("methodCall");
  
  	writer.startElement ("methodName");
  	writer.write (method);
  	writer.endElement ("methodName");
  
  	writer.startElement ("params");
  	int l = params.size ();
  	for (int i=0; i<l; i++) {
  	    writer.startElement ("param");
  	    writeObject (params.elementAt (i), writer);
  	    writer.endElement ("param");
  	}
  	writer.endElement ("params");
  	writer.endElement ("methodCall");
      }
  
  
      ////////////////////////////////////////////////////////////////
      // methods called by XML parser
  
      /**
       * Method called by SAX driver.
       */
      public void characters (char ch[], int start,
              int length) throws SAXException
      {
          if (!readCdata)
              return;
          cdata.append (ch, start, length);
      }
  
      /**
        * Method called by SAX driver.
       */
      public void endElement (String name) throws SAXException
      {
  
          if (debug)
              System.err.println ("endElement: "+name);
  
          // finalize character data, if appropriate
          if (currentValue != null && readCdata)
          {
              currentValue.characterData (cdata.toString ());
              cdata.setLength (0);
              readCdata = false;
          }
  
          if ("value".equals (name))
          {
              int depth = values.size ();
              // Only handle top level objects or objects contained in arrays here.
              // For objects contained in structs, wait for </member> (see code below).
              if (depth < 2 ||
                      values.elementAt (depth - 2).hashCode () != STRUCT)
              {
                  Value v = currentValue;
                  values.pop ();
                  if (depth < 2)
                  {
                      // This is a top-level object
                      objectParsed (v.value);
                      currentValue = null;
                  }
                  else
                  {
                      // add object to sub-array; if current container is a struct, add later (at </member>)
                      currentValue = (Value) values.peek ();
                      currentValue.endElement (v);
                  }
              }
          }
  
          // Handle objects contained in structs.
          if ("member".equals (name))
          {
              Value v = currentValue;
              values.pop ();
              currentValue = (Value) values.peek ();
              currentValue.endElement (v);
          }
  
          else if ("methodName".equals (name))
          {
              methodName = cdata.toString ();
              cdata.setLength (0);
              readCdata = false;
          }
      }
  
  
      /**
        * Method called by SAX driver.
        */
      public void startElement (String name,
              AttributeList atts) throws SAXException
      {
  
          if (debug)
              System.err.println ("startElement: "+name);
  
          if ("value".equals (name))
          {
              // System.err.println ("starting value");
              Value v = new Value ();
              values.push (v);
              currentValue = v;
              // cdata object is reused
              cdata.setLength(0);
              readCdata = true;
          }
  
          else if ("methodName".equals (name))
          {
              cdata.setLength(0);
              readCdata = true;
          }
  
          else if ("name".equals (name))
          {
              cdata.setLength(0);
              readCdata = true;
          }
  
          else if ("string".equals (name))
          {
              // currentValue.setType (STRING);
              cdata.setLength(0);
              readCdata = true;
          }
          else if ("i4".equals (name) || "int".equals (name))
          {
              currentValue.setType (INTEGER);
              cdata.setLength(0);
              readCdata = true;
          }
          else if ("boolean".equals (name))
          {
              currentValue.setType (BOOLEAN);
              cdata.setLength(0);
              readCdata = true;
          }
          else if ("double".equals (name))
          {
              currentValue.setType (DOUBLE);
              cdata.setLength(0);
              readCdata = true;
          }
          else if ("dateTime.iso8601".equals (name))
          {
              currentValue.setType (DATE);
              cdata.setLength(0);
              readCdata = true;
          }
          else if ("base64".equals (name))
          {
              currentValue.setType (BASE64);
              cdata.setLength(0);
              readCdata = true;
          }
          else if ("struct".equals (name))
              currentValue.setType (STRUCT);
          else if ("array".equals (name))
              currentValue.setType (ARRAY);
      }
  
  
      public void error (SAXParseException e) throws SAXException
      {
          System.err.println ("Error parsing XML: "+e);
          // errorLevel = RECOVERABLE;
          // errorMsg = e.toString ();
      }
  
      public void fatalError(SAXParseException e) throws SAXException
      {
          System.err.println ("Fatal error parsing XML: "+e);
          // errorLevel = FATAL;
          // errorMsg = e.toString ();
      }
  
      /**
        * This represents an XML-RPC Value while the request is being parsed.
        */
      class Value
      {
  
          int type;
          Object value;
          // the name to use for the next member of struct values
          String nextMemberName;
  
          Hashtable struct;
          Vector array;
  
          /**
           * Constructor.
           */
          public Value ()
          {
              this.type = STRING;
          }
  
          /**
            * Notification that a new child element has been parsed.
            */
          public void endElement (Value child)
          {
              if (type == ARRAY)
                  array.addElement (child.value);
              else if (type == STRUCT)
                  struct.put (nextMemberName, child.value);
          }
  
          /**
            * Set the type of this value. If it's a container, create the corresponding java container.
            */
          public void setType (int type)
          {
              // System.err.println ("setting type to "+types[type]);
              this.type = type;
              if (type == ARRAY)
                  value = array = new Vector ();
              if (type == STRUCT)
                  value = struct = new Hashtable ();
          }
  
          /**
            * Set the character data for the element and interpret it according to the
            * element type
            */
          public void characterData (String cdata)
          {
              switch (type)
              {
                  case INTEGER:
                      value = new Integer (cdata.trim ());
                      break;
                  case BOOLEAN:
                      value = new Boolean ("1".equals (cdata.trim ()));
                      break;
                  case DOUBLE:
                      value = new Double (cdata.trim ());
                      break;
                  case DATE:
                      try
                      {
                          value = format.parse (cdata.trim ());
                      }
                      catch (ParseException p)
                      {
                          // System.err.println ("Exception while parsing date: "+p);
                          throw new RuntimeException (p.getMessage ());
                      }
                      break;
                  case BASE64:
                      sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder ();
                      try {
                          value = decoder.decodeBuffer (cdata);
                      } catch (IOException x) {
                          throw new RuntimeException ("Error decoding base64 tag: "+x.getMessage ());
                      }
                      break;
                  case STRING:
                      value = cdata;
                      break;
                  case STRUCT:
                      // this is the name to use for the next member of this struct
                      nextMemberName = cdata;
                      break;
              }
          }
  
          // This is a performance hack to get the type of a value without casting the Object.
          // It breaks the contract of method hashCode, but it doesn't matter since
          // Value objects are never used as keys in Hashtables.
          public int hashCode ()
          {
              return type;
          }
  
          public String toString ()
          {
              return (types[type] + " element "+value);
          }
      }
  
  
      // A quick and dirty XML writer.
      class XmlWriter
      {
  
          StringBuffer buf;
          String enc;
  
          public XmlWriter (StringBuffer buf)
          {
              this.buf = buf;
              buf.append ("<?xml version=\"1.0\"?>");
          }
  
          public void startElement (String elem)
          {
              buf.append ("<");
              buf.append (elem);
              buf.append (">");
          }
  
          public void endElement (String elem)
          {
              buf.append ("</");
              buf.append (elem);
              buf.append (">");
          }
  
          public void emptyElement (String elem)
          {
              buf.append ("<");
              buf.append (elem);
              buf.append ("/>");
          }
  
  
          public void chardata (String text)
          {
              int l = text.length ();
              for (int i = 0; i < l; i++)
              {
                  char c = text.charAt (i);
                  switch (c)
                  {
                      case '<' :
                          buf.append ("&lt;");
                          break;
                      case '>' :
                          buf.append ("&gt;");
                          break;
                      case '&' :
                          buf.append ("&amp;");
                          break;
                      default :
                          buf.append (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 ();
          }
  
      }
  
  }
  
  
  
  
  
  1.1                  xml-rpc/src/java/org/apache/xmlrpc/applet/XmlRpcApplet.java
  
  Index: XmlRpcApplet.java
  ===================================================================
  package org.apache.xmlrpc.applet;
  
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "XML-RPC" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  
  import java.applet.*;
  import java.util.*;
  import java.io.IOException;
  import java.net.*;
  
  
  /**
   *  An applet that provides basic XML-RPC client functionality. 
   */
  public class XmlRpcApplet extends Applet {
      
      SimpleXmlRpcClient client;
  
  
      /** 
       * Initialize the XML-RPC client, trying to get the port number from the applet parameter tags. 
       * The default for port is 80. The client connects to the server this applet came from.
       */
      public void initClient () {
  	int port = 80;
  	String p = getParameter ("PORT");
  	if (p != null) try {
  	    port = Integer.parseInt (p);
  	} catch (NumberFormatException nfx) {
  	    System.out.println ("Error parsing port: "+nfx);
  	}
  	initClient (port);
      }
  
      /** 
       * Initialize the XML-RPC client with the specified port and the server this applet came from.
       */
      public void initClient (int port) {
  	String uri = getParameter ("URI");
  	if (uri == null)
  	    uri = "/RPC2";
  	else if (!uri.startsWith ("/"))
  	    uri = "/"+uri;
  	initClient (port, uri);
      }
  
      /** 
       * Initialize the XML-RPC client with the specified port and request path and the server this applet came from.
       */
      public void initClient (int port, String uri) {
  	String host = getCodeBase ().getHost ();
  	try {
  	    URL url = new URL ("http://"+host+":"+port+uri);
  	    System.out.println ("XML-RPC URL: "+url);
  	    client = new SimpleXmlRpcClient (url); 
  	} catch (MalformedURLException unlikely) {
  	    System.out.println ("Error constructing XML-RPC client for "+host+":"+port+": "+unlikely);
  	}
      }
      
      /** 
       * Calls the XML-RPC server with the specified methodname and argument list.
       */
      public Object execute (String methodName, Vector arguments) 
      throws XmlRpcException, IOException {
      	if (client == null)
      	    initClient ();
  	Object returnValue = null;
  	return returnValue = client.execute (methodName, arguments); 
      }
      
  
  }
  
  
  
  1.1                  xml-rpc/src/java/org/apache/xmlrpc/applet/XmlRpcException.java
  
  Index: XmlRpcException.java
  ===================================================================
  package org.apache.xmlrpc.applet;
  
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "XML-RPC" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  
  /**
   * This is thrown by the XmlRpcClient if the remote server reported an error. If something
   * went wrong at a lower level (e.g. no http connection) an IOException will be thrown instead.
   */
  public class XmlRpcException extends Exception {
  
      /**
       * The fault code of the exception. For servers based on this library, this will always be 0.
       * (If there are predefined error codes, they should be in the XML-RPC spec.)
       */
      public final int code;
  
      public XmlRpcException (int code, String message) {
  	super (message);
  	this.code = code;
      }
  
  }