update Directory, Fountain, JSReflection, SOAP, XMLRPC to use baskets and new JS...
[org.ibex.js.git] / src / org / ibex / js / XMLRPC.java
index a3dc331..44324e0 100644 (file)
@@ -5,10 +5,8 @@
 package org.ibex.js;
 
 import java.io.*;
-import java.util.*;
 import org.ibex.net.*;
 import org.ibex.util.*;
-import org.ibex.crypto.*;
 
 /**
  *  An XML-RPC client implemented as a JavaScript Host Object. See the
@@ -32,7 +30,7 @@ import org.ibex.crypto.*;
  *         convert.
  *  </ol>
  */
-public class XMLRPC extends JS {
+public class XMLRPC extends JS.Immutable {
 
     public XMLRPC(String url, String method) {
         this.http = url.startsWith("stdio:") ? HTTP.stdio : new HTTP(url);
@@ -46,11 +44,15 @@ public class XMLRPC extends JS {
 
 
     /** this holds character content as we read it in -- since there is only one per instance, we don't support mixed content */
-    protected AccessibleCharArrayWriter content = new AccessibleCharArrayWriter(100);
+    protected PublicCharArrayWriter content = new PublicCharArrayWriter(100);
+    public static final class PublicCharArrayWriter extends CharArrayWriter {
+        public PublicCharArrayWriter(int i) { super(i); }
+        public char[] buf;
+    };
     protected String url = null;         ///< the url to connect to
     protected String method = null;      ///< the method name to invoke on the remove server
     protected HTTP http = null;          ///< the HTTP connection to use
-    private Hash tracker;                ///< used to detect multi-ref data
+    private Basket.Map tracker;          ///< used to detect multi-ref data
     protected boolean fault = false;     ///< True iff the return value is a fault (and should be thrown as an exception)
 
 
@@ -75,39 +77,40 @@ public class XMLRPC extends JS {
      *  popped off the stack and inserted into the struct (third
      *  element on stack).
      */
-    protected Vec objects = null;
+    protected Basket.Array objects = null;
+    private void setLast(Object o) { objects.set(objects.size() - 1, o); }
 
 
     // Recieve ////////////////////////////////////////////////////////////////
 
     private class Helper extends XML {
-        public Helper() { super(BUFFER_SIZE); }
+        public Helper() { super(BUFFER_SIZE, true); }
 
-        public void startElement(XML.Element c) {
+        public void startElement(Tree.Element c) {
             content.reset();
             //#switch(c.getLocalName())
             case "fault": fault = true;
-            case "struct": objects.setElementAt(new JS.O(), objects.size() - 1);
-            case "array": objects.setElementAt(null, objects.size() - 1);
-            case "value": objects.addElement("");
+            case "struct": setLast(new JS.Obj());
+            case "array": setLast(null);
+            case "value": objects.add("");
             //#end
         }
         
-        public void endElement(XML.Element c) {
+        public void endElement(Tree.Element c) {
             //#switch(c.getLocalName())
-            case "int": objects.setElementAt(new Integer(new String(content.getBuf(), 0, content.size())), objects.size() - 1);
-            case "i4": objects.setElementAt(new Integer(new String(content.getBuf(), 0, content.size())), objects.size() - 1);
-            case "boolean": objects.setElementAt(content.getBuf()[0] == '1' ? Boolean.TRUE : Boolean.FALSE, objects.size() - 1);
-            case "string": objects.setElementAt(new String(content.getBuf(), 0, content.size()), objects.size() - 1);
-            case "double": objects.setElementAt(new Double(new String(content.getBuf(), 0, content.size())), objects.size() - 1);
+            case "int": setLast(new Integer(new String(content.buf, 0, content.size())));
+            case "i4": setLast(new Integer(new String(content.buf, 0, content.size())));
+            case "boolean": setLast(content.buf[0] == '1' ? Boolean.TRUE : Boolean.FALSE);
+            case "string": setLast(new String(content.buf, 0, content.size()));
+            case "double": setLast(new Double(new String(content.buf, 0, content.size())));
             case "base64":
-                objects.setElementAt(new Fountain.ByteArray(Base64.decode(new String(content.getBuf(), 0, content.size())),
-                                                          null), objects.size() - 1);
-            case "name": objects.addElement(new String(content.getBuf(), 0, content.size()));
-            case "value": if ("".equals(objects.lastElement()))
-                objects.setElementAt(new String(content.getBuf(), 0, content.size()), objects.size() - 1);
+                setLast(new Fountain.ByteArray(Encode.fromBase64(new String(content.buf, 0, content.size())),
+                                                          null));
+            case "name": objects.add(new String(content.buf, 0, content.size()));
+            case "value": if ("".equals(objects.peek()))
+                setLast(new String(content.buf, 0, content.size()));
             case "dateTime.iso8601":
-                String s = new String(content.getBuf(), 0, content.size());
+                String s = new String(content.buf, 0, content.size());
                 
                 // strip whitespace
                 int i=0;
@@ -125,33 +128,34 @@ public class XMLRPC extends JS {
                                                            (double)0
                                                            );
                     nd.setTime(JSDate.internalUTC(date));
-                    objects.setElementAt(nd, objects.size() - 1);
+                    setLast(nd);
                     
                 } catch (Exception e) {
                     throw new RuntimeException("ibex.net.rpc.xml.recieve.malformedDateTag" +
                                     "the server sent a <dateTime.iso8601> tag which was malformed: " + s);
                 }
             case "member":
-                JS memberValue = (JS)objects.elementAt(objects.size() - 1);
-                JS memberName = (JS)objects.elementAt(objects.size() - 2);
-                JS struct = (JS)objects.elementAt(objects.size() - 3);
+                JS memberValue = (JS)objects.get(objects.size() - 1);
+                JS memberName = (JS)objects.get(objects.size() - 2);
+                JS struct = (JS)objects.get(objects.size() - 3);
                 try {
                     struct.put(memberName, memberValue);
                 } catch (JSExn e) {
                     throw new Error("this should never happen");
                 }
-                objects.setSize(objects.size() - 2);
+                objects.pop();
+                objects.pop();
             case "data":
                 int i;
-                for(i=objects.size() - 1; objects.elementAt(i) != null; i--);
+                for(i=objects.size() - 1; objects.get(i) != null; i--);
                 JSArray arr = new JSArray();
                 try {
-                    for(int j = i + 1; j<objects.size(); j++) arr.put(Script.N(j - i - 1), (JS)objects.elementAt(j));
+                    for(int j = i + 1; j<objects.size(); j++) arr.put(Script.N(j - i - 1), (JS)objects.get(j));
                 } catch (JSExn e) {
                     throw new Error("this should never happen");
                 }
-                objects.setElementAt(arr, i);
-                objects.setSize(i + 1);
+                objects.set(i, arr);
+                objects.add(null);
             //#end            
             content.reset();
         }
@@ -178,9 +182,9 @@ public class XMLRPC extends JS {
         content.append(method);
         content.append("</methodName>\n");
         content.append("        <params>\n");
-        for(int i=0; i<args.length(); i++) {
+        for(int i=0; i < args.size(); i++) {
             content.append("            <param>\n");
-            appendObject(args.elementAt(i), content);
+            appendObject(args.get(i), content);
             content.append("            </param>\n");
         }
         content.append("        </params>\n");
@@ -224,7 +228,7 @@ public class XMLRPC extends JS {
                         System.arraycopy(buf, 0, writebuf, 0, numread);
                     }
                     sb.append("              ");
-                    sb.append(new String(Base64.encode(writebuf)));
+                    sb.append(new String(Encode.toBase64(writebuf)));
                     sb.append("\n");
                 }
                 sb.append("\n              </base64></value>\n");
@@ -278,7 +282,7 @@ public class XMLRPC extends JS {
             tracker.put(o, Script.B(true));
             sb.append("                <value><array><data>\n");
             JSArray a = (JSArray)o;
-            for(int i=0; i<a.length(); i++) appendObject(a.elementAt(i), sb);
+            for(int i=0; i < a.size(); i++) appendObject(a.get(i), sb);
             sb.append("                </data></array></value>\n");
 
         } else if (o instanceof JS) {
@@ -287,8 +291,8 @@ public class XMLRPC extends JS {
             JS j = (JS)o;
             sb.append("                <value><struct>\n");
             Enumeration e = j.keys();
-            while(e.hasMoreElements()) {
-                Object key = e.nextElement();
+            while (e.hasNext()) {
+                Object key = e.next();
                 sb.append("                <member><name>" + key + "</name>\n");
                 appendObject(j.get((JS)key), sb);
                 sb.append("                </member>\n");
@@ -323,33 +327,32 @@ public class XMLRPC extends JS {
     */
 
     // FIXME need to reenable backgrounding logic
-    final Object call(final JS.UnpauseCallback callback, final JSArray args) {
+    final Object call(final Pausable callback, final JSArray args) {
         try {
             if (Log.rpc) Log.info(this, "call to " + url + " : " + method);
-            if (tracker == null) tracker = new Hash();
-            if (objects == null) objects = new Vec();
+            if (tracker == null) tracker = new Basket.HashMap();
+            if (objects == null) objects = new Basket.Array();
             String request = buildRequest(args);
             if (Log.rpc) Log.info(this, "send:\n" + request);
             InputStream is = http.POST("text/xml", request, null, null);
             BufferedReader br = new BufferedReader(new InputStreamReader(is));
             try {
                 new Helper().parse(br);
-               if (fault) throw new JSExn((JS)objects.elementAt(0));
-                final JS result = (objects.size() == 0 ? (JS)null : ((JS)objects.elementAt(0)));
-                return (new Task() { public void perform() throws JSExn { callback.unpause(result); }});
+                if (fault) throw new JSExn((JS)objects.get(0));
+                final JS result = (objects.size() == 0 ? (JS)null : ((JS)objects.get(0)));
+                return (new Callable() { public Object run(Object o) throws Exception {
+                    return callback.run(result); }});
             } finally {
                 tracker.clear();
-                objects.setSize(0);
+                objects.clear();
             }
         } catch (final JSExn e) {
-            final Exception e2 = e;
-            return (new Task() { public void perform() throws JSExn { callback.unpause((JSExn)e2); }});
+            return (new Callable() { public Object run(Object o) throws Exception {
+                return callback.run(e); }});
         } catch (final IOException e) {
-            final Exception e2 = e;
-            return (new Task() { public void perform() throws JSExn { callback.unpause(new JSExn(e2.getMessage())); }});
-        } catch (final XML.Exn e) {
-            final Exception e2 = e;
-            return (new Task() { public void perform() throws JSExn { callback.unpause(new JSExn(e2.getMessage())); }});
+            final String msg = e.getMessage();
+            return (new Callable() { public Object run(Object o) throws Exception {
+                return callback.run(new JSExn(msg)); }});
         }
     }
 }