+ public int hashCode() { return graftee.hashCode(); }
+ public InputStream getInputStream(String s) throws IOException { return graftee.getInputStream(s); }
+ public Object get(Object key) { return replaced_key.equals(key) ? replaced_val : graftee.get(key); }
+ public String getDescriptiveName() { return graftee.getDescriptiveName(); }
+ public Res getParent() { return graftee.getParent(); }
+ public Object callMethod(Object method, Array args, boolean checkOnly) throws JS.Exn {
+ if (!replaced_key.equals(method)) return graftee.callMethod(method, args, checkOnly);
+ if (replaced_val instanceof Callable) return checkOnly ? Boolean.TRUE : ((Callable)replaced_val).call(args);
+ if (checkOnly) return Boolean.FALSE;
+ throw new JS.Exn("attempt to call non-function");
+ }
+ public Number coerceToNumber() { return graftee.coerceToNumber(); }
+ public String coerceToString() { return graftee.coerceToString(); }
+ public boolean coerceToBoolean() { return graftee.coerceToBoolean(); }
+ public String typeName() { return graftee.typeName(); }
+ }
+
+ /** shadow resource which replaces the graft */
+ public static class ProgressWatcher extends Res {
+ final Res watchee;
+ JS.CompiledFunction callback;
+ ProgressWatcher(Res watchee, JS.CompiledFunction callback) { this.watchee = watchee; this.callback = callback; }
+ public String getDescriptiveName() { return watchee.getDescriptiveName(); }
+ public InputStream getInputStream(String s) throws IOException {
+ final InputStream is = watchee.getInputStream(s);
+ return new FilterInputStream(is) {
+ int bytesDownloaded = 0;
+ public int read() throws IOException {
+ int ret = super.read();
+ if (ret != -1) bytesDownloaded++;
+ return ret;
+ }
+ public int read(byte[] b, int off, int len) throws IOException {
+ int ret = super.read(b, off, len);
+ if (ret != 1) bytesDownloaded += ret;
+ Scheduler.add(new Scheduler.Task() { public Object call(Object arg) {
+ JS.Array args = new JS.Array();
+ args.addElement(new Integer(bytesDownloaded));
+ args.addElement(new Integer(is instanceof KnownLength ? ((KnownLength)is).getLength() : 0));
+ // FIXME
+ // new JS.Thread(callback, callbackScope).resume();
+ return null;
+ } });
+ return ret;
+ }
+ };