-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
+// Copyright 2000-2005 the Contributors, as shown in the revision logs.
+// Licensed under the Apache Public Source License 2.0 ("the License").
+// You may not use this file except in compliance with the License.
+
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
* 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);
public XMLRPC(String url, String method, XMLRPC httpSource) {
this.http = httpSource.http; this.url = url; this.method = method; }
public JS get(JS name) throws JSExn {
- return new XMLRPC(url, (method.equals("") ? "" : method + ".") + JS.toString(name), this); }
+ return new XMLRPC(url, (method.equals("") ? "" : method + ".") + JSU.toString(name), this); }
/** 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)
* 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;
(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(JS.N(j - i - 1), (JS)objects.elementAt(j));
+ for(int j = i + 1; j<objects.size(); j++) arr.put(JSU.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();
}
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");
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");
} else if (o instanceof JSArray) {
if (tracker.get(o) != null) throw new JSExn("attempted to send multi-ref data structure via XML-RPC");
- tracker.put(o, JS.B(true));
+ tracker.put(o, JSU.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) {
if (tracker.get(o) != null) throw new JSExn("attempted to send multi-ref data structure via XML-RPC");
- tracker.put(o, JS.B(true));
+ tracker.put(o, JSU.B(true));
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");
*/
// 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.Hash();
+ 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)); }});
}
}
}