From: crawshaw Date: Thu, 6 Jan 2005 19:56:46 +0000 (+0000) Subject: update Directory, Fountain, JSReflection, SOAP, XMLRPC to use baskets and new JS... X-Git-Url: http://git.megacz.com/?p=org.ibex.js.git;a=commitdiff_plain;h=5a5f5ef235158d513c1f2879dc916b115a4fa9d0 update Directory, Fountain, JSReflection, SOAP, XMLRPC to use baskets and new JS interface darcs-hash:20050106195646-2eb37-c91d643766e08eb395699a04a6433c7e5e3daab0.gz --- diff --git a/src/org/ibex/js/Directory.java b/src/org/ibex/js/Directory.java index 07ef38a..0c0fc73 100644 --- a/src/org/ibex/js/Directory.java +++ b/src/org/ibex/js/Directory.java @@ -5,7 +5,6 @@ package org.ibex.js; import org.ibex.util.*; -import java.util.*; import java.io.*; // FEATURE: support for move @@ -38,7 +37,7 @@ import java.io.*; * argument that points to a non-directory File, this class will * delete that file and create a directory! */ -public class Directory extends JS { +public class Directory extends JS.Immutable { File f; @@ -66,21 +65,21 @@ public class Directory extends JS { public void put(JS key0, JS val) throws JSExn { try { if (key0 == null) return; - String key = toString(key0); - File f2 = new File(f.getAbsolutePath() + File.separatorChar + FileNameEncoder.encode(key)); + String key = Script.toString(key0); + File f2 = new File(f.getAbsolutePath() + File.separatorChar + Encode.toFilename(key)); destroy(f2); if (val == null) return; if (val instanceof JSPrimitive) { OutputStream out = new FileOutputStream(f2); Writer w = new OutputStreamWriter(out); - w.write(toString(val)); + w.write(Script.toString(val)); w.flush(); out.close(); } else { Directory d2 = new Directory(f2); JS.Enumeration e = val.keys(); - while(e.hasMoreElements()) { - JS k = e.nextElement(); + while(e.hasNext()) { + JS k = e.next(); JS v = val.get(k); d2.put(k, v); } @@ -93,8 +92,8 @@ public class Directory extends JS { public JS get(JS key0) throws JSExn { try { if (key0 == null) return null; - String key = toString(key0); - File f2 = new File(f.getAbsolutePath() + File.separatorChar + FileNameEncoder.encode(key)); + String key = Script.toString(key0); + File f2 = new File(f.getAbsolutePath() + File.separatorChar + Encode.toFilename(key)); if (!f2.exists()) return null; if (f2.isDirectory()) return new Directory(f2); char[] chars = new char[((int)f2.length()) * 2]; @@ -110,12 +109,12 @@ public class Directory extends JS { } } - public Enumeration keys() { + public JS.Enumeration keys() { final String[] elements = f.list(); - return new Enumeration(null) { + return new JS.Enumeration(null) { int i = 0; - public boolean _hasMoreElements() { return i < elements.length; } - public JS _nextElement() { return Script.S(FileNameEncoder.decode(elements[i++])); } + public boolean _hasNext() { return i < elements.length; } + public JS _next() { return Script.S(Encode.fromFilename(elements[i++])); } }; } } diff --git a/src/org/ibex/js/Fountain.java b/src/org/ibex/js/Fountain.java index c015f4c..f1bf14b 100644 --- a/src/org/ibex/js/Fountain.java +++ b/src/org/ibex/js/Fountain.java @@ -15,7 +15,7 @@ import org.ibex.net.*; * be totally independent of the others (ie separate stream position * and state) although they draw from the same data source. */ -public abstract class Fountain extends JS.O implements JS.Cloneable { +public abstract class Fountain extends JS.Immutable implements JS.Cloneable { // Public Interface ////////////////////////////////////////////////////////////////////////////// @@ -23,8 +23,7 @@ public abstract class Fountain extends JS.O implements JS.Cloneable { public static class NotCacheableException extends Exception { } // streams are "sealed" by default to prevent accidental object leakage - public void put(Object key, Object val) { } - private Cache getCache = new Cache(100); + private Cache getCache = new Cache(100, true); protected Object _get(Object key) { return null; } public final Object get(Object key) { Object ret = getCache.get(key); @@ -43,7 +42,7 @@ public abstract class Fountain extends JS.O implements JS.Cloneable { //public String toString() { return "Stream.HTTP:" + url; } public HTTP(String url) { while (url.endsWith("/")) url = url.substring(0, url.length() - 1); this.url = url; } public Object _get(Object key) { return new HTTP(url + "/" + (String)key); } - public String getCacheKey(Vec path) throws NotCacheableException { return url; } + public String getCacheKey(Basket.List path) throws NotCacheableException { return url; } public InputStream getInputStream() throws IOException { return new org.ibex.net.HTTP(url).GET(null, null); } } diff --git a/src/org/ibex/js/JSReflection.java b/src/org/ibex/js/JSReflection.java index 4d6ec04..d6ecd75 100644 --- a/src/org/ibex/js/JSReflection.java +++ b/src/org/ibex/js/JSReflection.java @@ -4,13 +4,11 @@ package org.ibex.js; -import org.ibex.util.*; -import java.io.*; -import java.util.*; import java.lang.reflect.*; /** Automatic JS-ification via Reflection (not for use in the core) */ -public class JSReflection extends JS { +public class JSReflection extends JS.Immutable { + private static final JS.Method METHOD = new JS.Method(); public static JS wrap(Object o) throws JSExn { if (o == null) return null; @@ -24,28 +22,25 @@ public class JSReflection extends JS { throw new JSExn("Reflection object tried to return a " + o.getClass().getName()); } - public static class Array extends JS { + public static class Array extends JS.Immutable { final Object[] arr; public Array(Object[] arr) { this.arr = arr; } // FEATURE: Add a JSCounterEnumeration public Enumeration keys() throws JSExn { return new Enumeration(null) { private int n = 0; - public boolean _hasMoreElements() { return n < arr.length; } - public JS _nextElement() { - return n >= arr.length ? null : Script.N(n++); - } + public boolean _hasNext() { return n < arr.length; } + public JS _next() { return Script.N(n++); } }; } - public JS get(JS key) throws JSExn { return wrap(arr[toInt(key)]); } - public void put(JS key, JS val) throws JSExn { throw new JSExn("can't write to org.ibex.js.Reflection.Array's"); } + public JS get(JS key) throws JSExn { return wrap(arr[Script.toInt(key)]); } } // FIXME public static class Hash { } // FIXME public Enumeration keys() throws JSExn { } public JS get(JS key) throws JSExn { - String k = toString(key); + String k = Script.toString(key); try { Field f = this.getClass().getField(k); return wrap(f.get(this)); @@ -54,7 +49,7 @@ public class JSReflection extends JS { } catch (SecurityException nfe) { } try { - Method[] methods = this.getClass().getMethods(); + java.lang.reflect.Method[] methods = this.getClass().getMethods(); for(int i=0; i 0 && content.toString().trim().length() > 0) { // remove ourselves - Object me = objects.elementAt(objects.size() - 1); + Object me = objects.get(objects.size() - 1); if (fault || me instanceof String) { - objects.removeElementAt(objects.size() - 1); - objects.addElement(new String(content.getBuf(), 0, content.size()).intern()); + objects.pop(); + objects.push(new String(content.buf, 0, content.size()).intern()); content.reset(); } else if (me instanceof byte[]) { - objects.removeElementAt(objects.size() - 1); - objects.addElement(new Fountain.ByteArray(Base64.decode(new String(content.getBuf(), 0, content.size())), null)); + objects.pop(); + objects.push(new Fountain.ByteArray(Encode.fromBase64(new String(content.buf, 0, content.size())), null)); content.reset(); } else if (me instanceof Integer) { - objects.removeElementAt(objects.size() - 1); - objects.addElement(new Integer(new String(content.getBuf(), 0, content.size()))); + objects.pop(); + objects.push(new Integer(new String(content.buf, 0, content.size()))); content.reset(); } else if (me instanceof Boolean) { - objects.removeElementAt(objects.size() - 1); - String s = new String(content.getBuf(), 0, content.size()).trim(); - if (s.equals("1") || s.equals("true")) objects.addElement(Boolean.TRUE); - else objects.addElement(Boolean.FALSE); + objects.pop(); + String s = new String(content.buf, 0, content.size()).trim(); + if (s.equals("1") || s.equals("true")) objects.push(Boolean.TRUE); + else objects.push(Boolean.FALSE); content.reset(); } else if (me instanceof Double) { - objects.removeElementAt(objects.size() - 1); - objects.addElement(new Double(new String(content.getBuf(), 0, content.size()))); + objects.pop(); + objects.push(new Double(new String(content.buf, 0, content.size()))); content.reset(); } else { // okay, we got PCDATA for what is supposedly a // struct... somebody's not adding their type info... - String s = new String(content.getBuf(), 0, content.size()).trim(); + String s = new String(content.buf, 0, content.size()).trim(); boolean hasdot = false; for(int i=0; i 1 ? (JS)objects.elementAt(objects.size() - 2) : (JS)null; + JS parent = objects.size() > 1 ? (JS)objects.get(objects.size() - 2) : (JS)null; // we want to fold stuff back into the fault object if (objects.size() < 2) return; // our parent "should" be an aggregate type -- add ourselves to it. if (parent != null && parent instanceof JSArray) { - objects.removeElementAt(objects.size() - 1); - ((JSArray)parent).addElement(me); + objects.pop(); + ((JSArray)parent).push(me); } else if (parent != null && parent instanceof JS) { - objects.removeElementAt(objects.size() - 1); + objects.pop(); try { ((JS)parent).put(Script.S(name), me); } catch (JSExn e) { @@ -196,7 +193,7 @@ public class SOAP extends XMLRPC { 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("\r\n"); } sb.append(((Boolean)o).booleanValue() ? "1" : "0"); @@ -228,16 +225,16 @@ public class SOAP extends XMLRPC { } else if (o instanceof JSArray) { JSArray a = (JSArray)o; - sb.append(" <" + name + " SOAP-ENC:arrayType=\"xsd:ur-type[" + a.length() + "]\">"); - for(int i=0; i"); + for(int i=0; i\r\n"); } else if (o instanceof JS) { JS j = (JS)o; sb.append(" <" + name + ">"); - Enumeration e = j.keys(); - while(e.hasMoreElements()) { - Object key = e.nextElement(); + JS.Enumeration e = j.keys(); + while(e.hasNext()) { + Object key = e.next(); appendObject((String)key, j.get((JS)key), sb); } sb.append("\r\n"); @@ -260,11 +257,11 @@ public class SOAP extends XMLRPC { content.append(method); content.append(nameSpace != null ? " xmlns=\"" + nameSpace + "\"" : ""); content.append(">\r\n"); - if (args.length() > 0) { - Enumeration e = ((JS)args.elementAt(0)).keys(); - while(e.hasMoreElements()) { - JS key = (JS)e.nextElement(); - appendObject(((JSString)key).coerceToString(), ((JS)args.elementAt(0)).get(key), content); + if (args.size() > 0) { + JS.Enumeration e = ((JS)args.get(0)).keys(); + while(e.hasNext()) { + JS key = (JS)e.next(); + appendObject(((JSString)key).coerceToString(), ((JS)args.get(0)).get(key), content); } } content.append(" \r\n"); diff --git a/src/org/ibex/js/XMLRPC.java b/src/org/ibex/js/XMLRPC.java index a3dc331..44324e0 100644 --- a/src/org/ibex/js/XMLRPC.java +++ b/src/org/ibex/js/XMLRPC.java @@ -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. * */ -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 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\n"); content.append(" \n"); - for(int i=0; i\n"); - appendObject(args.elementAt(i), content); + appendObject(args.get(i), content); content.append(" \n"); } content.append(" \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 \n"); @@ -278,7 +282,7 @@ public class XMLRPC extends JS { tracker.put(o, Script.B(true)); sb.append(" \n"); JSArray a = (JSArray)o; - for(int i=0; i\n"); } else if (o instanceof JS) { @@ -287,8 +291,8 @@ public class XMLRPC extends JS { JS j = (JS)o; sb.append(" \n"); Enumeration e = j.keys(); - while(e.hasMoreElements()) { - Object key = e.nextElement(); + while (e.hasNext()) { + Object key = e.next(); sb.append(" " + key + "\n"); appendObject(j.get((JS)key), sb); sb.append(" \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)); }}); } } }