From e1a626a6cccf4846b90c98821f597429bf095d71 Mon Sep 17 00:00:00 2001 From: brian Date: Tue, 6 Jul 2004 12:14:00 +0000 Subject: [PATCH 1/1] stream cleanup darcs-hash:20040706121400-24bed-142e9a11c29ccbf41e3e7fde786a4069ccd84e6c.gz --- src/org/ibex/core/Ibex.java | 40 ++++++++++++++----------- src/org/ibex/core/Template.java | 2 +- src/org/ibex/graphics/Font.java | 2 +- src/org/ibex/graphics/Picture.java | 2 +- src/org/ibex/js/JS.java | 9 ++++-- src/org/ibex/js/Stream.java | 57 ++++++++++++++++++++---------------- 6 files changed, 65 insertions(+), 47 deletions(-) diff --git a/src/org/ibex/core/Ibex.java b/src/org/ibex/core/Ibex.java index 58969ae..66d9189 100644 --- a/src/org/ibex/core/Ibex.java +++ b/src/org/ibex/core/Ibex.java @@ -15,11 +15,11 @@ public final class Ibex extends JS implements JS.Cloneable { // FIXME remove this private final JS rr; - public Ibex(Stream rr) { try { this.rr = bless(rr);} catch(JSExn e) { throw new Error("should never happen"); } } + public Ibex(Stream rr) { try { this.rr = bless(rr);} catch(JSExn e) { throw new Error("should never happen: " + e); } } public JS resolveString(String str, boolean permitAbsolute) throws JSExn { if (str.indexOf("://") != -1) { - if (permitAbsolute) return (Stream)url2res(str); + if (permitAbsolute) return url2res(str); throw new JSExn("absolute URL " + str + " not permitted here"); } // root-relative @@ -171,10 +171,10 @@ public final class Ibex extends JS implements JS.Cloneable { return ((JS)a).jsclone(); case "bless": return bless((JS)a); case "ui.browser": Platform.newBrowserWindow(JS.toString(a)); return null; - case "stream.unzip": return new Stream.Zip((Stream)a); - case "stream.uncab": return new Stream.Cab((Stream)a); + case "stream.unzip": return a == null ? null : new Stream.Zip(a); + case "stream.uncab": return a == null ? null : new Stream.Cab(a); case "stream.cache": - try { return new Stream.CachedStream((Stream)a, "resources", true); } + try { return a == null ? null : new Stream.CachedStream(a, "resources", true); } catch (Stream.NotCacheableException e) { throw new JSExn("this resource cannot be cached"); } case "stream.url": { String url = JS.toString(a); @@ -196,22 +196,23 @@ public final class Ibex extends JS implements JS.Cloneable { case "crypto.sha1": /* FEATURE */ return null; case "crypto.rc4": /* FEATURE */ return null; case "stream.parse.html": throw new JSExn("not implemented yet"); //return null; - case "stream.parse.xml": new XMLHelper((JS)b).doParse((JS)a); return null; + case "stream.parse.xml": if(a == null) return null; new XMLHelper(b).doParse(a); return null; // FIXME backgrounding - case "stream.parse.utf8": try { return JS.S(new String(InputStreamToByteArray.convert(Stream.getInputStream(a)))); } + case "stream.parse.utf8": if(a == null) return null; + try { return JS.S(new String(InputStreamToByteArray.convert(a.getInputStream()))); } catch (Exception e) { Log.warn(this, e); } //#end break; case 2: //#switch(name) - case "stream.watch": return new Stream.ProgressWatcher((Stream)a, (JS)b); + case "stream.watch": return new Stream.ProgressWatcher(a, b); case "regexp": return new JSRegexp(a, b); //#end case 3: //#switch(name) - case "ui.font.height": return N(Font.getFont((Stream)a, JS.toInt(b)).textheight(JS.toString(c))); + case "ui.font.height": return N(Font.getFont(a, JS.toInt(b)).textheight(JS.toString(c))); case "ui.font.wait": throw new Error("FIXME: ibex.ui.font.wait not implemented"); - case "ui.font.width": return N(Font.getFont((Stream)a, JS.toInt(b)).textwidth(JS.toString(c))); + case "ui.font.width": return N(Font.getFont(a, JS.toInt(b)).textwidth(JS.toString(c))); //#end break; } @@ -224,7 +225,7 @@ public final class Ibex extends JS implements JS.Cloneable { throw new JSExn("invalid number of arguments ("+nargs+") for ibex object method "+name+"()"); } - public Stream url2res(String url) throws JSExn { + public JS url2res(String url) throws JSExn { if (url.startsWith("http://")) return new Stream.HTTP(url); else if (url.startsWith("https://")) return new Stream.HTTP(url); else if (url.startsWith("data:")) return new Stream.ByteArray(Base64.decode(url.substring(5)), null); @@ -333,7 +334,7 @@ public final class Ibex extends JS implements JS.Cloneable { public void doParse(JS s) throws JSExn { try { - parse(new BufferedReader(new InputStreamReader(Stream.getInputStream(s)))); + parse(new BufferedReader(new InputStreamReader(s.getInputStream()))); } catch (Wrapper e) { throw e.wrapee; } catch (XML.Exn e) { @@ -370,15 +371,16 @@ public final class Ibex extends JS implements JS.Cloneable { if (!(js instanceof Blessing)) return null; return (Blessing)js; } + // FEATURE: This is a gross hack public InputStream getImage() throws JSExn { try { - InputStream in = Stream.getInputStream(this); + InputStream in = getInputStream(); if (in != null) return in; } catch (IOException e) { /* DELIBERATE */ } String[] exts = new String[] { ".png", ".jpeg", ".gif" }; for (int i=0; i < exts.length; i++) try { - InputStream in = Stream.getInputStream(parent.get(JS.S(JS.toString(parentkey) + exts[i]))); + InputStream in = parent.get(JS.S(JS.toString(parentkey) + exts[i])).getInputStream(); if (in != null) return in; } catch (IOException f) { /* DELIBERATE */ } return null; @@ -387,9 +389,8 @@ public final class Ibex extends JS implements JS.Cloneable { try { if (t == null) { // FEATURE: Might want to handle the ".t" part better - JS res = (JS) parent.get(JS.S(JS.toString(parentkey) + ".t")); - // FIXME: need a better description (Stream.toString()) - t = Template.buildTemplate(JS.toString(parentkey), res, ibex); + JS res = parent.get(JS.S(JS.toString(parentkey) + ".t")); + t = Template.buildTemplate(description(), res, ibex); } return t != null ? t.staticScope : null; } catch (Exception e) { @@ -397,6 +398,11 @@ public final class Ibex extends JS implements JS.Cloneable { return null; } } + private String description() { + String s = JS.debugToString(parentkey); + for(Blessing b = parent; b != null; b = b.parent) s = JS.debugToString(parentkey) + "." + s; + return s; + } public JS call(JS a, JS b, JS c, JS[] rest, int nargs) throws JSExn { if (nargs != 1) throw new JSExn("can only call a template with one arg"); getStatic(); diff --git a/src/org/ibex/core/Template.java b/src/org/ibex/core/Template.java index 7f342dd..efa3bbb 100644 --- a/src/org/ibex/core/Template.java +++ b/src/org/ibex/core/Template.java @@ -157,7 +157,7 @@ public class Template { public TemplateHelper(String sourceName, JS s, Ibex ibex) throws XML.Exn, IOException, JSExn { this.sourceName = sourceName; this.ibex = ibex; - InputStream is = Stream.getInputStream(s); + InputStream is = s.getInputStream(); Ibex.Blessing b = Ibex.Blessing.getBlessing(s).parent; while(b != null) { if(b.parentkey != null) initial_uri = JS.toString(b.parentkey) + (initial_uri.equals("") ? "" : "." + initial_uri); diff --git a/src/org/ibex/graphics/Font.java b/src/org/ibex/graphics/Font.java index 35e9cf2..96c65c4 100644 --- a/src/org/ibex/graphics/Font.java +++ b/src/org/ibex/graphics/Font.java @@ -136,7 +136,7 @@ public class Font { try { Log.info(Font.class, "loading font " + JS.debugToString(res)); - InputStream is = Stream.getInputStream(res); + InputStream is = res.getInputStream(); byte[] fontstream = InputStreamToByteArray.convert(is); rt.free(loadedStreamAddr); loadedStreamAddr = rt.xmalloc(fontstream.length); diff --git a/src/org/ibex/graphics/Picture.java b/src/org/ibex/graphics/Picture.java index 572823c..ed0e8a9 100644 --- a/src/org/ibex/graphics/Picture.java +++ b/src/org/ibex/graphics/Picture.java @@ -46,7 +46,7 @@ public class Picture { new java.lang.Thread() { public void run() { InputStream in = null; try { - in = b == null ? Stream.getInputStream(stream) : b.getImage(); + in = b == null ? stream.getInputStream() : b.getImage(); } catch (IOException e) { Log.error(Picture.class, e); } catch (JSExn e) { Log.error(Picture.class, e); } diff --git a/src/org/ibex/js/JS.java b/src/org/ibex/js/JS.java index 04d7edd..68fac37 100644 --- a/src/org/ibex/js/JS.java +++ b/src/org/ibex/js/JS.java @@ -18,12 +18,16 @@ public abstract class JS { public Enumeration keys() throws JSExn { throw new JSExn("you can't enumerate the keys of this object (class=" + getClass().getName() +")"); } public JS get(JS key) throws JSExn { return null; } public void put(JS key, JS val) throws JSExn { throw new JSExn("" + key + " is read only (class=" + getClass().getName() +")"); } + + public InputStream getInputStream() throws IOException { + throw new IOException("this object doesn't have a stream associated with it " + getClass().getName() + ")"); + } public final boolean hasTrap(JS key) { return getTrap(key) != null; } public JS callMethod(JS method, JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn { throw new JSExn("method not found (" + JS.debugToString(method) + ")"); - } + } // FIXME: JSArgs objects, pointers into stack frame public JS call(JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn { @@ -87,7 +91,7 @@ public abstract class JS { JS _unclone() { return clonee.unclone(); } public JS getClonee() { return clonee; } public Clone(JS clonee) throws JSExn { - if(!(clonee instanceof Cloneable)) throw new JSExn("" + getClass().getName() + " isn't cloneable"); + if(!(clonee instanceof Cloneable)) throw new JSExn("" + clonee.getClass().getName() + " isn't cloneable"); this.clonee = clonee; } public boolean jsequals(JS o) { return unclone().jsequals(o.unclone()); } @@ -100,6 +104,7 @@ public abstract class JS { public JS call(JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn { return clonee.call(a0, a1, a2, rest, nargs); } + public InputStream getInputStream() throws IOException { return clonee.getInputStream(); } } // Static Interpreter Control Methods /////////////////////////////////////////////////////////////// diff --git a/src/org/ibex/js/Stream.java b/src/org/ibex/js/Stream.java index e69c28c..8ed5759 100644 --- a/src/org/ibex/js/Stream.java +++ b/src/org/ibex/js/Stream.java @@ -17,21 +17,24 @@ public abstract class Stream extends JS implements JS.Cloneable { // Public Interface ////////////////////////////////////////////////////////////////////////////// - // FIXME: This should be in JS, "everything has a stream" - public static InputStream getInputStream(JS js) throws IOException { return ((Stream)js.unclone()).getInputStream();} + /*public static InputStream getInputStream(JS js) throws IOException { return ((Stream)js.unclone()).getInputStream();}*/ public static class NotCacheableException extends Exception { } private Cache getCache = new Cache(100); - // FEATURE: Mandate that Streams use only String keys? - protected JS _get(JS key) throws JSExn { return null; } + public abstract JS _get(String key); public final JS get(JS key) throws JSExn { JS ret = (JS) getCache.get(key); - if (ret == null) getCache.put(key, ret = _get(key)); + if (ret == null) getCache.put(key, ret = _get(JS.toString(key))); return ret; } // Private Interface ////////////////////////////////////////////////////////////////////////////// + static String getCacheKey(JS s) throws NotCacheableException { + if(s instanceof Stream) return ((Stream)s).getCacheKey(); + throw new NotCacheableException(); + } + public abstract InputStream getInputStream() throws IOException; protected String getCacheKey() throws NotCacheableException { throw new NotCacheableException(); } @@ -39,9 +42,8 @@ public abstract class Stream extends JS implements JS.Cloneable { // FEATURE: Only instansiate only ibex.net.HTTP, share with all substreams public static class HTTP extends Stream { private String url; - public String coerceToString() { return "Stream.HTTP:" + url; } public HTTP(String url) { while (url.endsWith("/")) url = url.substring(0, url.length() - 1); this.url = url; } - public JS _get(JS key) throws JSExn { return new HTTP(url + "/" + JS.toString(key)); } + public JS _get(String key) { return new HTTP(url + "/" + key); } public String getCacheKey(Vec path) throws NotCacheableException { return url; } public InputStream getInputStream() throws IOException { return new org.ibex.net.HTTP(url).GET(); } } @@ -54,30 +56,30 @@ public abstract class Stream extends JS implements JS.Cloneable { public String getCacheKey() throws NotCacheableException { if (cacheKey == null) throw new NotCacheableException(); return cacheKey; } public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(bytes); } + public JS _get(String key) { return null; } } /** a file */ public static class File extends Stream { private String path; public File(String path) { this.path = path; } - public String coerceToString() { return "file:" + path; } public String getCacheKey() throws NotCacheableException { throw new NotCacheableException(); /* already on disk */ } public InputStream getInputStream() throws IOException { return new FileInputStream(path); } - public JS _get(JS key) throws JSExn { return new File(path + java.io.File.separatorChar + JS.toString(key)); } + public JS _get(String key) { return new File(path + java.io.File.separatorChar + key); } } /** "unwrap" a Zip archive */ public static class Zip extends Stream { - private Stream parent; + private JS parent; private String path; - public Zip(Stream parent) { this(parent, null); } - public Zip(Stream parent, String path) { + public Zip(JS parent) { this(parent, null); } + public Zip(JS parent, String path) { while(path != null && path.startsWith("/")) path = path.substring(1); this.parent = parent; this.path = path; } - public String getCacheKey() throws NotCacheableException { return parent.getCacheKey() + "!zip:"; } - public JS _get(JS key) throws JSExn { return new Zip(parent, path==null?JS.toString(key):path+'/'+JS.toString(key)); } + public String getCacheKey() throws NotCacheableException { return getCacheKey(parent) + "!zip:"; } + public JS _get(String key) { return new Zip(parent, path==null?key:path+'/'+key); } public InputStream getInputStream() throws IOException { InputStream pis = parent.getInputStream(); ZipInputStream zis = new ZipInputStream(pis); @@ -90,12 +92,12 @@ public abstract class Stream extends JS implements JS.Cloneable { /** "unwrap" a Cab archive */ public static class Cab extends Stream { - private Stream parent; + private JS parent; private String path; - public Cab(Stream parent) { this(parent, null); } - public Cab(Stream parent, String path) { this.parent = parent; this.path = path; } - public String getCacheKey() throws NotCacheableException { return parent.getCacheKey() + "!cab:"; } - public JS _get(JS key) throws JSExn { return new Cab(parent, path==null?JS.toString(key):path+'/'+JS.toString(key)); } + public Cab(JS parent) { this(parent, null); } + public Cab(JS parent, String path) { this.parent = parent; this.path = path; } + public String getCacheKey() throws NotCacheableException { return getCacheKey(parent) + "!cab:"; } + public JS _get(String key) { return new Cab(parent, path==null?key:path+'/'+key); } public InputStream getInputStream() throws IOException { return new MSPack(parent.getInputStream()).getInputStream(path); } } @@ -103,14 +105,15 @@ public abstract class Stream extends JS implements JS.Cloneable { public static class Builtin extends Stream { public String getCacheKey() throws NotCacheableException { throw new NotCacheableException(); } public InputStream getInputStream() throws IOException { return Platform.getBuiltinInputStream(); } + public JS _get(String key) { return null; } } /** shadow resource which replaces the graft */ public static class ProgressWatcher extends Stream { - final Stream watchee; + final JS watchee; JS callback; - public ProgressWatcher(Stream watchee, JS callback) { this.watchee = watchee; this.callback = callback; } - public String getCacheKey() throws NotCacheableException { return watchee.getCacheKey(); } + public ProgressWatcher(JS watchee, JS callback) { this.watchee = watchee; this.callback = callback; } + public String getCacheKey() throws NotCacheableException { return getCacheKey(watchee); } public InputStream getInputStream() throws IOException { final InputStream is = watchee.getInputStream(); return new FilterInputStream(is) { @@ -131,28 +134,32 @@ public abstract class Stream extends JS implements JS.Cloneable { } }; } + public JS _get(String s) { return null; } } /** subclass from this if you want a CachedInputStream for each path */ public static class CachedStream extends Stream { - private Stream parent; + private JS parent; private boolean disk = false; private String key; + private String s; public String getCacheKey() throws NotCacheableException { return key; } CachedInputStream cis = null; - public CachedStream(Stream p, String s, boolean d) throws NotCacheableException { - this.parent = p; this.disk = d; this.key = p.getCacheKey(); + public CachedStream(JS p, String s, boolean d) throws NotCacheableException { + this.parent = p; this.s = s; this.disk = d; this.key = getCacheKey(p); } public InputStream getInputStream() throws IOException { if (cis != null) return cis.getInputStream(); if (!disk) { cis = new CachedInputStream(parent.getInputStream()); } else { + // FEATURE: Move LocalStorage into org.ibex.js or move this out java.io.File f = org.ibex.core.LocalStorage.Cache.getCacheFileForKey(key); if (f.exists()) return new FileInputStream(f); cis = new CachedInputStream(parent.getInputStream(), f); } return cis.getInputStream(); } + public JS _get(String s) { return null; } } } -- 1.7.10.4