package org.ibex.js;
import org.ibex.util.*;
-import java.util.*;
import java.io.*;
// FEATURE: support for move
* 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;
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);
}
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];
}
}
- 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++])); }
};
}
}
* 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 //////////////////////////////////////////////////////////////////////////////
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);
//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); }
}
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;
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));
} catch (SecurityException nfe) { }
try {
- Method[] methods = this.getClass().getMethods();
+ java.lang.reflect.Method[] methods = this.getClass().getMethods();
for(int i=0; i<methods.length; i++) if (methods[i].getName().equals(k)) return METHOD;
} catch (SecurityException nfe) { }
return null;
throw new JSExn("put() not supported yet");
}
- public JS callMethod(JS method, JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn {
- String k = toString(method);
+ public JS call(JS method, JS[] args) throws JSExn {
+ String k = Script.toString(method);
try {
- Method[] methods = this.getClass().getMethods();
+ java.lang.reflect.Method[] methods = this.getClass().getMethods();
for(int j=0; j<methods.length; j++) {
- if (methods[j].getName().equals(k) && methods[j].getParameterTypes().length == nargs) {
- Object[] args = new Object[nargs];
- for(int i = 0; i<args.length; i++) {
- if (i==0) args[i] = a0;
- else if (i==1) args[i] = a1;
- else if (i==2) args[i] = a2;
- else args[i] = rest[i-3];
- }
- return wrap(methods[j].invoke(this, args));
+ if (methods[j].getName().equals(k) &&
+ methods[j].getParameterTypes().length == args.length) {
+ return wrap(methods[j].invoke(this, (Object[])args));
}
}
} catch (IllegalAccessException nfe) {
package org.ibex.js;
import java.io.*;
-import java.util.*;
-import org.ibex.net.*;
import org.ibex.util.*;
-import org.ibex.crypto.*;
/**
* A partial RPC-style SOAP 1.1 client. Implemented from the SOAP 1.1
if (name.equals("SOAP-ENV:Fault")) fault = true;
// add a generic struct; we'll change this if our type is different
- objects.addElement(new JS.O());
+ objects.push(new JS.Obj());
for(int i=0; i<keys.length; i++) {
String key = keys[i];
String value = vals[i].toString();
if (key.endsWith("ype")) {
if (value.endsWith("boolean")) {
- objects.removeElementAt(objects.size() - 1);
- objects.addElement(Script.B(true));
+ objects.pop();
+ objects.push(Script.B(true));
} else if (value.endsWith("int")) {
- objects.removeElementAt(objects.size() - 1);
- objects.addElement(Script.N(0));
+ objects.pop();
+ objects.push(Script.N(0));
} else if (value.endsWith("double")) {
- objects.removeElementAt(objects.size() - 1);
- objects.addElement(Script.N(0.0));
+ objects.pop();
+ objects.push(Script.N(0.0));
} else if (value.endsWith("string")) {
- objects.removeElementAt(objects.size() - 1);
- objects.addElement(Script.S(""));
+ objects.pop();
+ objects.push(Script.S(""));
} else if (value.endsWith("base64")) {
- objects.removeElementAt(objects.size() - 1);
- objects.addElement(new byte[] { });
+ objects.pop();
+ objects.push(new byte[] { });
} else if (value.endsWith("null")) {
- objects.removeElementAt(objects.size() - 1);
- objects.addElement(null);
+ objects.pop();
+ objects.push(null);
} else if (value.endsWith("arrayType") || value.endsWith("JSArray") || key.endsWith("arrayType")) {
- objects.removeElementAt(objects.size() - 1);
- objects.addElement(new JSArray());
+ objects.pop();
+ objects.push(new JSArray());
}
}
}
if (content.size() > 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<s.length(); i++) {
if (s.charAt(i) == '.') hasdot = true;
if (!Character.isDigit(s.charAt(i))) {
- objects.removeElementAt(objects.size() - 1);
- objects.addElement(s);
+ objects.pop();
+ objects.push(s);
return;
}
}
if (hasdot) {
- objects.removeElementAt(objects.size() - 1);
- objects.addElement(new Double(s));
+ objects.pop();
+ objects.push(new Double(s));
} else {
- objects.removeElementAt(objects.size() - 1);
- objects.addElement(new Integer(s));
+ objects.pop();
+ objects.push(new Integer(s));
}
content.reset();
}
}
// remove ourselves
- JS me = (JS)objects.elementAt(objects.size() - 1);
+ JS me = (JS)objects.get(objects.size() - 1);
// find our parent
- JS parent = objects.size() > 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) {
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");
} 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<a.length(); i++) appendObject("item", a.elementAt(i), sb);
+ sb.append(" <" + name + " SOAP-ENC:arrayType=\"xsd:ur-type[" + a.size() + "]\">");
+ for(int i=0; i<a.size(); i++) appendObject("item", a.get(i), sb);
sb.append("</" + name + ">\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("</" + name + ">\r\n");
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(" </" + method + "></SOAP-ENV:Body></SOAP-ENV:Envelope>\r\n");
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);
/** 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(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();
}
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");
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) {
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.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)); }});
}
}
}