+ /** "unwrap" a Cab archive */
+ public static class Cab extends Res {
+ private Res parent;
+ Cab(Res parent) { this.parent = parent; }
+ public String getCacheKey() throws NotCacheableException { return parent.getCacheKey() + "!cab:"; }
+ public InputStream getInputStream(String path) throws IOException {
+ if (path.startsWith("/")) path = path.substring(1);
+ return new org.xwt.translators.MSPack(parent.getInputStream()).getInputStream(path);
+ }
+ }
+
+ /** the Builtin resource */
+ public static class Builtin extends Res {
+ public Builtin() { };
+ public String getCacheKey() throws NotCacheableException { throw notCacheable; } // not cacheable
+ public InputStream getInputStream(String path) throws IOException {
+ if (!path.equals("")) throw new IOException("the builtin resource has no subresources");
+ return Platform.getBuiltinInputStream();
+ }
+ }
+
+ /** what you get when you reference a subresource */
+ public static class Ref extends Res {
+ Res parent;
+ Object key;
+ Ref(Res parent, Object key) { this.parent = parent; this.key = key; }
+ public String getCacheKey() throws NotCacheableException { return parent.getCacheKey() + "/" + key; }
+ public Res addExtension(String extension) {
+ return ((String)key).endsWith(extension) ? this : new Ref(parent, key + extension); }
+ public InputStream getInputStream(String path) throws IOException { return parent.getInputStream("/" + key + path); }
+ }
+
+ /** shadow resource which replaces the graft */
+ public static class ProgressWatcher extends Res {
+ final Res watchee;
+ JSFunction callback;
+ ProgressWatcher(Res watchee, JSFunction callback) { this.watchee = watchee; this.callback = callback; }
+ public String getCacheKey() throws NotCacheableException { return watchee.getCacheKey(); }
+ 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 void perform() {
+ JSArray args = new JSArray();
+ args.addElement(new Integer(bytesDownloaded));
+ args.addElement(new Integer(is instanceof KnownLength ? ((KnownLength)is).getLength() : 0));
+ callback.call(args);
+ } });
+ return ret;
+ }
+ };
+ }
+ }