Can initialize VM with classpath composed of a JAR file and read resources from it emul
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Fri, 01 Feb 2013 18:42:07 +0100
branchemul
changeset 644cfbd4eecb941
parent 643 a2c0afa35c09
child 645 a947e379f161
Can initialize VM with classpath composed of a JAR file and read resources from it
vm/src/main/java/org/apidesign/vm4brwsr/VM.java
vm/src/main/java/org/apidesign/vm4brwsr/Zips.java
vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java
     1.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Fri Feb 01 18:35:21 2013 +0100
     1.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Fri Feb 01 18:42:07 2013 +0100
     1.3 @@ -32,6 +32,7 @@
     1.4      static {
     1.5          // uses VMLazy to load dynamic classes
     1.6          VMLazy.init();
     1.7 +        Zips.init();
     1.8      }
     1.9  
    1.10      @Override
    1.11 @@ -116,6 +117,12 @@
    1.12              + "    var args = arguments;\n"
    1.13              + "    var loader = {};\n"
    1.14              + "    loader.vm = vm;\n"
    1.15 +            + "    if (args.length == 1 && typeof args[0] !== 'function') {;\n"
    1.16 +            + "      var classpath = args[0];\n"
    1.17 +            + "      args[0] = function(name) {\n"
    1.18 +            + "        return vm.org_apidesign_vm4brwsr_Zips(false).loadFromCp___3B_3Ljava_lang_Object_2Ljava_lang_String_2(classpath, name);\n"
    1.19 +            + "      };\n"
    1.20 +            + "    };\n"
    1.21              + "    loader.loadClass = function(name) {\n"
    1.22              + "      var attr = name.replace__Ljava_lang_String_2CC('.','_');\n"
    1.23              + "      var fn = vm[attr];\n"
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Zips.java	Fri Feb 01 18:42:07 2013 +0100
     2.3 @@ -0,0 +1,97 @@
     2.4 +/**
     2.5 + * Back 2 Browser Bytecode Translator
     2.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     2.7 + *
     2.8 + * This program is free software: you can redistribute it and/or modify
     2.9 + * it under the terms of the GNU General Public License as published by
    2.10 + * the Free Software Foundation, version 2 of the License.
    2.11 + *
    2.12 + * This program is distributed in the hope that it will be useful,
    2.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.15 + * GNU General Public License for more details.
    2.16 + *
    2.17 + * You should have received a copy of the GNU General Public License
    2.18 + * along with this program. Look for COPYING file in the top folder.
    2.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    2.20 + */
    2.21 +package org.apidesign.vm4brwsr;
    2.22 +
    2.23 +import java.io.IOException;
    2.24 +import java.net.URL;
    2.25 +import java.util.zip.ZipEntry;
    2.26 +import java.util.zip.ZipInputStream;
    2.27 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
    2.28 +
    2.29 +/** Conversion from classpath to load function.
    2.30 + *
    2.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    2.32 + */
    2.33 +final class Zips {
    2.34 +    private Zips() {
    2.35 +    }
    2.36 +    
    2.37 +    public static void init() {
    2.38 +    }
    2.39 +    
    2.40 +    public static byte[] loadFromCp(Object[] classpath, String res) {
    2.41 +        for (int i = 0; i < classpath.length; i++) {
    2.42 +            Object c = classpath[i];
    2.43 +            if (c instanceof String) {
    2.44 +                try {
    2.45 +                    c = classpath[i] = toZip((String)c);
    2.46 +                } catch (IOException ex) {
    2.47 +                    classpath[i] = ex;
    2.48 +                }
    2.49 +            }
    2.50 +            if (c instanceof Zips) {
    2.51 +                Object checkRes = ((Zips)c).findRes(res);
    2.52 +                if (checkRes instanceof byte[]) {
    2.53 +                    return (byte[])checkRes;
    2.54 +                }
    2.55 +            }
    2.56 +        }
    2.57 +        return null;
    2.58 +    }
    2.59 +
    2.60 +    @JavaScriptBody(args = { "res" }, body = "var r = this[res]; return r ? r : null;")
    2.61 +    private native byte[] findRes(String res);
    2.62 +
    2.63 +    @JavaScriptBody(args = { "res", "arr" }, body = "this[res] = arr;")
    2.64 +    private native void putRes(String res, byte[] arr);
    2.65 +    
    2.66 +    private static Zips toZip(String path) throws IOException {
    2.67 +        URL u = new URL(path);
    2.68 +        ZipInputStream zip = new ZipInputStream(u.openStream());
    2.69 +        Zips z = new Zips();
    2.70 +        for (;;) {
    2.71 +            ZipEntry entry = zip.getNextEntry();
    2.72 +            if (entry == null) {
    2.73 +                break;
    2.74 +            }
    2.75 +            byte[] arr = new byte[4096];
    2.76 +            int offset = 0;
    2.77 +            for (;;) {
    2.78 +                int len = zip.read(arr, offset, arr.length - offset);
    2.79 +                if (len == -1) {
    2.80 +                    break;
    2.81 +                }
    2.82 +                offset += len;
    2.83 +                if (offset == arr.length) {
    2.84 +                    enlargeArray(arr, arr.length + 4096);
    2.85 +                }
    2.86 +            }
    2.87 +            sliceArray(arr, offset);
    2.88 +            z.putRes(entry.getName(), arr);
    2.89 +        }
    2.90 +        return z;
    2.91 +    }
    2.92 +
    2.93 +    @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(0);")
    2.94 +    private static native void enlargeArray(byte[] arr, int len);
    2.95 +
    2.96 +    @JavaScriptBody(args = { "arr", "len" }, body = "arr.splice(len, arr.length - len);")
    2.97 +    private static native void sliceArray(byte[] arr, int len);
    2.98 +    
    2.99 +    
   2.100 +}
     3.1 --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java	Fri Feb 01 18:35:21 2013 +0100
     3.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java	Fri Feb 01 18:42:07 2013 +0100
     3.3 @@ -53,6 +53,26 @@
     3.4          return ret;
     3.5      }
     3.6      
     3.7 +    @JavaScriptBody(args = { "res", "path" }, body = 
     3.8 +          "var myvm = new bck2brwsr(path);\n"
     3.9 +        + "var cls = myvm.loadClass('java.lang.String');\n"
    3.10 +        + "return cls.getClass__Ljava_lang_Class_2().getResourceAsStream__Ljava_io_InputStream_2Ljava_lang_String_2(res);\n"
    3.11 +    )
    3.12 +    private static native Object loadVMResource(String res, String...path);
    3.13 +
    3.14 +    @HttpResource(path = "/readAnEntry.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip")
    3.15 +    @BrwsrTest  public void canVmLoadResourceFromZip() throws IOException {
    3.16 +        Object res = loadVMResource("/my/main/file.txt", "http:/readAnEntry.jar");
    3.17 +        assert res instanceof InputStream : "Got array of bytes: " + res;
    3.18 +        InputStream is = (InputStream)res;
    3.19 +        
    3.20 +        byte[] arr = new byte[4096];
    3.21 +        int len = is.read(arr);
    3.22 +        
    3.23 +        final String ret = new String(arr, 0, len, "UTF-8");
    3.24 +
    3.25 +        assertEquals(ret, "Hello World!", "Can read the bytes");
    3.26 +    }
    3.27      
    3.28      private static void assertEquals(Object real, Object exp, String msg) {
    3.29          assert Objects.equals(exp, real) : msg + " exp: " + exp + " real: " + real;