Moving Zip tests into right locations closure
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Fri, 09 May 2014 08:37:20 +0200
branchclosure
changeset 15510002739b6d1f
parent 1550 cb9e273dfd51
child 1552 5a840853d1a8
Moving Zip tests into right locations
rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/compact/tck/demo.static.calculator-TEST.jar
rt/emul/zip/pom.xml
rt/emul/zip/src/main/java/org/apidesign/bck2brwsr/vmzip/ZipResources.java
rt/emul/zip/src/test/java/org/apidesign/bck2brwsr/emul/zip/ZipEntryTest.java
rt/emul/zip/src/test/java/org/apidesign/bck2brwsr/emul/zip/ZipFileTest.java
rt/emul/zip/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipEntryTest.java
rt/emul/zip/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java
rt/emul/zip/src/test/resources/org/apidesign/bck2brwsr/emul/zip/demo.static.calculator-TEST.jar
rt/vm/src/main/java/org/apidesign/vm4brwsr/ClassPath.java
rt/vm/src/main/java/org/apidesign/vm4brwsr/ZipHandler.java
     1.1 Binary file rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/compact/tck/demo.static.calculator-TEST.jar has changed
     2.1 --- a/rt/emul/zip/pom.xml	Wed May 07 17:24:29 2014 +0200
     2.2 +++ b/rt/emul/zip/pom.xml	Fri May 09 08:37:20 2014 +0200
     2.3 @@ -47,5 +47,11 @@
     2.4              <scope>test</scope>
     2.5              <type>jar</type>
     2.6          </dependency>
     2.7 +        <dependency>
     2.8 +            <groupId>org.apidesign.bck2brwsr</groupId>
     2.9 +            <artifactId>vm4brwsr</artifactId>
    2.10 +            <version>${project.version}</version>
    2.11 +            <type>jar</type>
    2.12 +        </dependency>
    2.13      </dependencies>
    2.14 -</project>
    2.15 \ No newline at end of file
    2.16 +</project>
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/rt/emul/zip/src/main/java/org/apidesign/bck2brwsr/vmzip/ZipResources.java	Fri May 09 08:37:20 2014 +0200
     3.3 @@ -0,0 +1,115 @@
     3.4 +/**
     3.5 + * Back 2 Browser Bytecode Translator
     3.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     3.7 + *
     3.8 + * This program is free software: you can redistribute it and/or modify
     3.9 + * it under the terms of the GNU General Public License as published by
    3.10 + * the Free Software Foundation, version 2 of the License.
    3.11 + *
    3.12 + * This program is distributed in the hope that it will be useful,
    3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.15 + * GNU General Public License for more details.
    3.16 + *
    3.17 + * You should have received a copy of the GNU General Public License
    3.18 + * along with this program. Look for COPYING file in the top folder.
    3.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    3.20 + */
    3.21 +package org.apidesign.bck2brwsr.vmzip;
    3.22 +
    3.23 +import java.io.ByteArrayInputStream;
    3.24 +import java.io.IOException;
    3.25 +import java.io.InputStream;
    3.26 +import org.apidesign.bck2brwsr.core.Exported;
    3.27 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
    3.28 +import org.apidesign.bck2brwsr.emul.zip.FastJar;
    3.29 +import org.apidesign.vm4brwsr.Bck2Brwsr;
    3.30 +
    3.31 +/** Conversion from classpath to load function.
    3.32 + *
    3.33 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    3.34 + */
    3.35 +@Exported
    3.36 +public final class ZipResources implements Bck2Brwsr.Resources {
    3.37 +    private final FastJar fj;
    3.38 +
    3.39 +    @Exported
    3.40 +    public ZipResources(byte[] zipData) throws IOException {
    3.41 +//        long bef = timeNow();
    3.42 +        fj = new FastJar(zipData);
    3.43 +        for (FastJar.Entry e : fj.list()) {
    3.44 +            putRes(e.name, e);
    3.45 +        }
    3.46 +//        log("Iterating thru " + path + " took " + (timeNow() - bef) + "ms");
    3.47 +    }
    3.48 +    
    3.49 +    @JavaScriptBody(args = { "arr" }, body = "return arr.length;")
    3.50 +    private static native int length(Object arr);
    3.51 +    @JavaScriptBody(args = { "arr", "index", "value" }, body = "arr[index] = value; return value;")
    3.52 +    private static native Object set(Object arr, int index, Object value);
    3.53 +    
    3.54 +    @JavaScriptBody(args = { "msg" }, body = "if (typeof console !== 'undefined') console.log(msg.toString());")
    3.55 +    private static native void log(String msg);
    3.56 +
    3.57 +    private byte[] findRes(String res) throws IOException {
    3.58 +        Object arr = findResImpl(res);
    3.59 +        if (arr instanceof FastJar.Entry) {
    3.60 +            long bef = timeNow();
    3.61 +            InputStream zip = fj.getInputStream((FastJar.Entry)arr);
    3.62 +            arr = readFully(new byte[512], zip);
    3.63 +            putRes(res, arr);
    3.64 +            log("Reading " + res + " took " + (timeNow() - bef) + "ms");
    3.65 +        }
    3.66 +        return (byte[]) arr;
    3.67 +    }
    3.68 +
    3.69 +    @Override
    3.70 +    public InputStream get(String resource) throws IOException {
    3.71 +        byte[] arr = findRes(resource);
    3.72 +        return arr == null ? null : new ByteArrayInputStream(arr);
    3.73 +    }
    3.74 +
    3.75 +    @JavaScriptBody(args = { "res" }, body = "var r = this[res]; return r ? r : null;")
    3.76 +    private native Object findResImpl(String res);
    3.77 +
    3.78 +    @JavaScriptBody(args = { "res", "arr" }, body = "this[res] = arr;")
    3.79 +    private native void putRes(String res, Object arr);
    3.80 +    
    3.81 +    @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(0);")
    3.82 +    private static native void enlargeBytes(byte[] arr, int len);
    3.83 +
    3.84 +    @JavaScriptBody(args = { "arr", "len" }, body = "arr.splice(len, arr.length - len);")
    3.85 +    private static native void sliceArray(byte[] arr, int len);
    3.86 +
    3.87 +    private static Object readFully(byte[] arr, InputStream zip) throws IOException {
    3.88 +        int offset = 0;
    3.89 +        for (;;) {
    3.90 +            int len = zip.read(arr, offset, arr.length - offset);
    3.91 +            if (len == -1) {
    3.92 +                break;
    3.93 +            }
    3.94 +            offset += len;
    3.95 +            if (offset == arr.length) {
    3.96 +                enlargeBytes(arr, arr.length + 4096);
    3.97 +            }
    3.98 +        }
    3.99 +        sliceArray(arr, offset);
   3.100 +        return arr;
   3.101 +    }
   3.102 +
   3.103 +    private static long timeNow() {
   3.104 +        double time = m();
   3.105 +        if (time >= 0) {
   3.106 +            return (long)time;
   3.107 +        }
   3.108 +        return org.apidesign.bck2brwsr.emul.lang.System.currentTimeMillis();
   3.109 +    }
   3.110 +    @JavaScriptBody(args = {}, body = 
   3.111 +        "if (typeof window.performance === 'undefined') return -1;\n"
   3.112 +      + "if (typeof window.performance.now === 'undefined') return -1;\n"
   3.113 +      + "return window.performance.now();"
   3.114 +    )
   3.115 +    private static native double m();
   3.116 +
   3.117 +    
   3.118 +}
     4.1 --- a/rt/emul/zip/src/test/java/org/apidesign/bck2brwsr/emul/zip/ZipEntryTest.java	Wed May 07 17:24:29 2014 +0200
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,67 +0,0 @@
     4.4 -/**
     4.5 - * Back 2 Browser Bytecode Translator
     4.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4.7 - *
     4.8 - * This program is free software: you can redistribute it and/or modify
     4.9 - * it under the terms of the GNU General Public License as published by
    4.10 - * the Free Software Foundation, version 2 of the License.
    4.11 - *
    4.12 - * This program is distributed in the hope that it will be useful,
    4.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.15 - * GNU General Public License for more details.
    4.16 - *
    4.17 - * You should have received a copy of the GNU General Public License
    4.18 - * along with this program. Look for COPYING file in the top folder.
    4.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
    4.20 - */
    4.21 -package org.apidesign.bck2brwsr.vmtest.impl;
    4.22 -
    4.23 -import java.io.ByteArrayInputStream;
    4.24 -import java.io.IOException;
    4.25 -import java.io.InputStream;
    4.26 -import org.apidesign.bck2brwsr.emul.zip.FastJar;
    4.27 -import org.testng.annotations.Test;
    4.28 -import static org.testng.Assert.*;
    4.29 -
    4.30 -/**
    4.31 - *
    4.32 - * @author Jaroslav Tulach <jtulach@netbeans.org>
    4.33 - */
    4.34 -@GenerateZip(name = "five.zip", contents = {
    4.35 -    "1.txt", "one",
    4.36 -    "2.txt", "duo",
    4.37 -    "3.txt", "three",
    4.38 -    "4.txt", "four",
    4.39 -    "5.txt", "five"
    4.40 -})
    4.41 -public class ZipEntryTest {
    4.42 -    @Test
    4.43 -    public void readEntriesEffectively() throws IOException {
    4.44 -        InputStream is = ZipEntryTest.class.getResourceAsStream("five.zip");
    4.45 -        byte[] arr = new byte[is.available()];
    4.46 -        int len = is.read(arr);
    4.47 -        assertEquals(len, arr.length, "Read fully");
    4.48 -        
    4.49 -        FastJar fj = new FastJar(arr);
    4.50 -        FastJar.Entry[] entrs = fj.list();
    4.51 -        
    4.52 -        assertEquals(5, entrs.length, "Five entries");
    4.53 -        
    4.54 -        for (int i = 1; i <= 5; i++) {
    4.55 -            FastJar.Entry en = entrs[i - 1];
    4.56 -            assertEquals(en.name, i + ".txt");
    4.57 -//            assertEquals(cis.cnt, 0, "Content of the file should be skipped, not read");
    4.58 -        }
    4.59 -        
    4.60 -        assertContent("three", fj.getInputStream(entrs[3 - 1]), "read OK");
    4.61 -        assertContent("five", fj.getInputStream(entrs[5 - 1]), "read OK");
    4.62 -    }
    4.63 -
    4.64 -    private static void assertContent(String exp, InputStream is, String msg) throws IOException {
    4.65 -        byte[] arr = new byte[512];
    4.66 -        int len = is.read(arr);
    4.67 -        String s = new String(arr, 0, len);
    4.68 -        assertEquals(exp, s, msg);
    4.69 -    }
    4.70 -}
     5.1 --- a/rt/emul/zip/src/test/java/org/apidesign/bck2brwsr/emul/zip/ZipFileTest.java	Wed May 07 17:24:29 2014 +0200
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,108 +0,0 @@
     5.4 -/**
     5.5 - * Back 2 Browser Bytecode Translator
     5.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     5.7 - *
     5.8 - * This program is free software: you can redistribute it and/or modify
     5.9 - * it under the terms of the GNU General Public License as published by
    5.10 - * the Free Software Foundation, version 2 of the License.
    5.11 - *
    5.12 - * This program is distributed in the hope that it will be useful,
    5.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.15 - * GNU General Public License for more details.
    5.16 - *
    5.17 - * You should have received a copy of the GNU General Public License
    5.18 - * along with this program. Look for COPYING file in the top folder.
    5.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
    5.20 - */
    5.21 -package org.apidesign.bck2brwsr.vmtest.impl;
    5.22 -
    5.23 -import java.io.IOException;
    5.24 -import java.io.InputStream;
    5.25 -import java.util.Objects;
    5.26 -import java.util.zip.ZipEntry;
    5.27 -import java.util.zip.ZipInputStream;
    5.28 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
    5.29 -import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
    5.30 -import org.apidesign.bck2brwsr.vmtest.Compare;
    5.31 -import org.apidesign.bck2brwsr.vmtest.Http;
    5.32 -import org.apidesign.bck2brwsr.vmtest.VMTest;
    5.33 -import org.testng.annotations.Factory;
    5.34 -
    5.35 -/**
    5.36 - *
    5.37 - * @author Jaroslav Tulach <jtulach@netbeans.org>
    5.38 - */
    5.39 -@GenerateZip(name = "readAnEntry.zip", contents = { 
    5.40 -    "my/main/file.txt", "Hello World!"
    5.41 -})
    5.42 -public class ZipFileTest {
    5.43 -    
    5.44 -    @Compare public String readAnEntry() throws IOException {
    5.45 -        InputStream is = ZipFileTest.class.getResourceAsStream("readAnEntry.zip");
    5.46 -        ZipInputStream zip = new ZipInputStream(is);
    5.47 -        ZipEntry entry = zip.getNextEntry();
    5.48 -        assertEquals(entry.getName(), "my/main/file.txt", "Correct entry");
    5.49 -
    5.50 -        byte[] arr = new byte[4096];
    5.51 -        int len = zip.read(arr);
    5.52 -        
    5.53 -        assertEquals(zip.getNextEntry(), null, "No next entry");
    5.54 -        
    5.55 -        final String ret = new String(arr, 0, len, "UTF-8");
    5.56 -        return ret;
    5.57 -    }
    5.58 -    
    5.59 -    @JavaScriptBody(args = { "res", "path" }, body = 
    5.60 -          "var myvm = bck2brwsr.apply(null, path);\n"
    5.61 -        + "var cls = myvm.loadClass('java.lang.String');\n"
    5.62 -        + "return cls.getClass__Ljava_lang_Class_2().getResourceAsStream__Ljava_io_InputStream_2Ljava_lang_String_2(res);\n"
    5.63 -    )
    5.64 -    private static native Object loadVMResource(String res, String...path);
    5.65 -
    5.66 -    @Http({
    5.67 -        @Http.Resource(path = "/readAnEntry.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip")
    5.68 -    })
    5.69 -    @BrwsrTest  public void canVmLoadResourceFromZip() throws IOException {
    5.70 -        Object res = loadVMResource("/my/main/file.txt", "/readAnEntry.jar");
    5.71 -        assert res instanceof InputStream : "Got array of bytes: " + res;
    5.72 -        InputStream is = (InputStream)res;
    5.73 -        
    5.74 -        byte[] arr = new byte[4096];
    5.75 -        int len = is.read(arr);
    5.76 -        
    5.77 -        final String ret = new String(arr, 0, len, "UTF-8");
    5.78 -
    5.79 -        assertEquals(ret, "Hello World!", "Can read the bytes");
    5.80 -    }
    5.81 -    
    5.82 -    @GenerateZip(name = "cpattr.zip", contents = { 
    5.83 -        "META-INF/MANIFEST.MF", "Manifest-Version: 1.0\n"
    5.84 -        + "Created-By: hand\n"
    5.85 -        + "Class-Path: realJar.jar\n\n\n"
    5.86 -    })
    5.87 -    @Http({
    5.88 -        @Http.Resource(path = "/readComplexEntry.jar", mimeType = "x-application/zip", content = "", resource="cpattr.zip"),
    5.89 -        @Http.Resource(path = "/realJar.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip"),
    5.90 -    })
    5.91 -    @BrwsrTest  public void understandsClassPathAttr() throws IOException {
    5.92 -        Object res = loadVMResource("/my/main/file.txt", "/readComplexEntry.jar");
    5.93 -        assert res instanceof InputStream : "Got array of bytes: " + res;
    5.94 -        InputStream is = (InputStream)res;
    5.95 -        
    5.96 -        byte[] arr = new byte[4096];
    5.97 -        int len = is.read(arr);
    5.98 -        
    5.99 -        final String ret = new String(arr, 0, len, "UTF-8");
   5.100 -
   5.101 -        assertEquals(ret, "Hello World!", "Can read the bytes from secondary JAR");
   5.102 -    }
   5.103 -    
   5.104 -    private static void assertEquals(Object real, Object exp, String msg) {
   5.105 -        assert Objects.equals(exp, real) : msg + " exp: " + exp + " real: " + real;
   5.106 -    }
   5.107 -    
   5.108 -    @Factory public static Object[] create() {
   5.109 -        return VMTest.create(ZipFileTest.class);
   5.110 -    }
   5.111 -}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/rt/emul/zip/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipEntryTest.java	Fri May 09 08:37:20 2014 +0200
     6.3 @@ -0,0 +1,66 @@
     6.4 +/**
     6.5 + * Back 2 Browser Bytecode Translator
     6.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     6.7 + *
     6.8 + * This program is free software: you can redistribute it and/or modify
     6.9 + * it under the terms of the GNU General Public License as published by
    6.10 + * the Free Software Foundation, version 2 of the License.
    6.11 + *
    6.12 + * This program is distributed in the hope that it will be useful,
    6.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.15 + * GNU General Public License for more details.
    6.16 + *
    6.17 + * You should have received a copy of the GNU General Public License
    6.18 + * along with this program. Look for COPYING file in the top folder.
    6.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    6.20 + */
    6.21 +package org.apidesign.bck2brwsr.vmtest.impl;
    6.22 +
    6.23 +import java.io.IOException;
    6.24 +import java.io.InputStream;
    6.25 +import org.apidesign.bck2brwsr.emul.zip.FastJar;
    6.26 +import org.testng.annotations.Test;
    6.27 +import static org.testng.Assert.*;
    6.28 +
    6.29 +/**
    6.30 + *
    6.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    6.32 + */
    6.33 +@GenerateZip(name = "five.zip", contents = {
    6.34 +    "1.txt", "one",
    6.35 +    "2.txt", "duo",
    6.36 +    "3.txt", "three",
    6.37 +    "4.txt", "four",
    6.38 +    "5.txt", "five"
    6.39 +})
    6.40 +public class ZipEntryTest {
    6.41 +    @Test
    6.42 +    public void readEntriesEffectively() throws IOException {
    6.43 +        InputStream is = ZipEntryTest.class.getResourceAsStream("five.zip");
    6.44 +        byte[] arr = new byte[is.available()];
    6.45 +        int len = is.read(arr);
    6.46 +        assertEquals(len, arr.length, "Read fully");
    6.47 +        
    6.48 +        FastJar fj = new FastJar(arr);
    6.49 +        FastJar.Entry[] entrs = fj.list();
    6.50 +        
    6.51 +        assertEquals(5, entrs.length, "Five entries");
    6.52 +        
    6.53 +        for (int i = 1; i <= 5; i++) {
    6.54 +            FastJar.Entry en = entrs[i - 1];
    6.55 +            assertEquals(en.name, i + ".txt");
    6.56 +//            assertEquals(cis.cnt, 0, "Content of the file should be skipped, not read");
    6.57 +        }
    6.58 +        
    6.59 +        assertContent("three", fj.getInputStream(entrs[3 - 1]), "read OK");
    6.60 +        assertContent("five", fj.getInputStream(entrs[5 - 1]), "read OK");
    6.61 +    }
    6.62 +
    6.63 +    private static void assertContent(String exp, InputStream is, String msg) throws IOException {
    6.64 +        byte[] arr = new byte[512];
    6.65 +        int len = is.read(arr);
    6.66 +        String s = new String(arr, 0, len);
    6.67 +        assertEquals(exp, s, msg);
    6.68 +    }
    6.69 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/rt/emul/zip/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java	Fri May 09 08:37:20 2014 +0200
     7.3 @@ -0,0 +1,108 @@
     7.4 +/**
     7.5 + * Back 2 Browser Bytecode Translator
     7.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     7.7 + *
     7.8 + * This program is free software: you can redistribute it and/or modify
     7.9 + * it under the terms of the GNU General Public License as published by
    7.10 + * the Free Software Foundation, version 2 of the License.
    7.11 + *
    7.12 + * This program is distributed in the hope that it will be useful,
    7.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.15 + * GNU General Public License for more details.
    7.16 + *
    7.17 + * You should have received a copy of the GNU General Public License
    7.18 + * along with this program. Look for COPYING file in the top folder.
    7.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    7.20 + */
    7.21 +package org.apidesign.bck2brwsr.vmtest.impl;
    7.22 +
    7.23 +import java.io.IOException;
    7.24 +import java.io.InputStream;
    7.25 +import java.util.Objects;
    7.26 +import java.util.zip.ZipEntry;
    7.27 +import java.util.zip.ZipInputStream;
    7.28 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
    7.29 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
    7.30 +import org.apidesign.bck2brwsr.vmtest.Compare;
    7.31 +import org.apidesign.bck2brwsr.vmtest.Http;
    7.32 +import org.apidesign.bck2brwsr.vmtest.VMTest;
    7.33 +import org.testng.annotations.Factory;
    7.34 +
    7.35 +/**
    7.36 + *
    7.37 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    7.38 + */
    7.39 +@GenerateZip(name = "readAnEntry.zip", contents = { 
    7.40 +    "my/main/file.txt", "Hello World!"
    7.41 +})
    7.42 +public class ZipFileTest {
    7.43 +    
    7.44 +    @Compare public String readAnEntry() throws IOException {
    7.45 +        InputStream is = ZipFileTest.class.getResourceAsStream("readAnEntry.zip");
    7.46 +        ZipInputStream zip = new ZipInputStream(is);
    7.47 +        ZipEntry entry = zip.getNextEntry();
    7.48 +        assertEquals(entry.getName(), "my/main/file.txt", "Correct entry");
    7.49 +
    7.50 +        byte[] arr = new byte[4096];
    7.51 +        int len = zip.read(arr);
    7.52 +        
    7.53 +        assertEquals(zip.getNextEntry(), null, "No next entry");
    7.54 +        
    7.55 +        final String ret = new String(arr, 0, len, "UTF-8");
    7.56 +        return ret;
    7.57 +    }
    7.58 +    
    7.59 +    @JavaScriptBody(args = { "res", "path" }, body = 
    7.60 +          "var myvm = bck2brwsr.apply(null, path);\n"
    7.61 +        + "var cls = myvm.loadClass('java.lang.String');\n"
    7.62 +        + "return cls.getClass__Ljava_lang_Class_2().getResourceAsStream__Ljava_io_InputStream_2Ljava_lang_String_2(res);\n"
    7.63 +    )
    7.64 +    private static native Object loadVMResource(String res, String...path);
    7.65 +
    7.66 +    @Http({
    7.67 +        @Http.Resource(path = "/readAnEntry.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip")
    7.68 +    })
    7.69 +    @BrwsrTest  public void canVmLoadResourceFromZip() throws IOException {
    7.70 +        Object res = loadVMResource("/my/main/file.txt", "/readAnEntry.jar");
    7.71 +        assert res instanceof InputStream : "Got array of bytes: " + res;
    7.72 +        InputStream is = (InputStream)res;
    7.73 +        
    7.74 +        byte[] arr = new byte[4096];
    7.75 +        int len = is.read(arr);
    7.76 +        
    7.77 +        final String ret = new String(arr, 0, len, "UTF-8");
    7.78 +
    7.79 +        assertEquals(ret, "Hello World!", "Can read the bytes");
    7.80 +    }
    7.81 +    
    7.82 +    @GenerateZip(name = "cpattr.zip", contents = { 
    7.83 +        "META-INF/MANIFEST.MF", "Manifest-Version: 1.0\n"
    7.84 +        + "Created-By: hand\n"
    7.85 +        + "Class-Path: realJar.jar\n\n\n"
    7.86 +    })
    7.87 +    @Http({
    7.88 +        @Http.Resource(path = "/readComplexEntry.jar", mimeType = "x-application/zip", content = "", resource="cpattr.zip"),
    7.89 +        @Http.Resource(path = "/realJar.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip"),
    7.90 +    })
    7.91 +    @BrwsrTest  public void understandsClassPathAttr() throws IOException {
    7.92 +        Object res = loadVMResource("/my/main/file.txt", "/readComplexEntry.jar");
    7.93 +        assert res instanceof InputStream : "Got array of bytes: " + res;
    7.94 +        InputStream is = (InputStream)res;
    7.95 +        
    7.96 +        byte[] arr = new byte[4096];
    7.97 +        int len = is.read(arr);
    7.98 +        
    7.99 +        final String ret = new String(arr, 0, len, "UTF-8");
   7.100 +
   7.101 +        assertEquals(ret, "Hello World!", "Can read the bytes from secondary JAR");
   7.102 +    }
   7.103 +    
   7.104 +    private static void assertEquals(Object real, Object exp, String msg) {
   7.105 +        assert Objects.equals(exp, real) : msg + " exp: " + exp + " real: " + real;
   7.106 +    }
   7.107 +    
   7.108 +    @Factory public static Object[] create() {
   7.109 +        return VMTest.create(ZipFileTest.class);
   7.110 +    }
   7.111 +}
     8.1 Binary file rt/emul/zip/src/test/resources/org/apidesign/bck2brwsr/emul/zip/demo.static.calculator-TEST.jar has changed
     9.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ClassPath.java	Wed May 07 17:24:29 2014 +0200
     9.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ClassPath.java	Fri May 09 08:37:20 2014 +0200
     9.3 @@ -19,6 +19,7 @@
     9.4  
     9.5  import java.io.ByteArrayInputStream;
     9.6  import java.io.IOException;
     9.7 +import java.io.InputStream;
     9.8  import java.net.URL;
     9.9  import org.apidesign.bck2brwsr.core.JavaScriptBody;
    9.10  
    9.11 @@ -46,9 +47,9 @@
    9.12              if (c instanceof String) {
    9.13                  try {
    9.14                      String url = (String)c;
    9.15 -                    final ZipHandler z = ZipHandler.toZip(url);
    9.16 +                    final Bck2Brwsr.Resources z = toZip(url);
    9.17                      c = set(classpath, i, z);
    9.18 -                    final byte[] man = z.findRes("META-INF/MANIFEST.MF");
    9.19 +                    final byte[] man = readBytes(z, "META-INF/MANIFEST.MF");
    9.20                      if (man != null) {
    9.21                          String mainClass = processClassPathAttr(man, url, classpath);
    9.22  //                        if (mainClass != null) {
    9.23 @@ -62,8 +63,8 @@
    9.24              }
    9.25              if (res != null) {
    9.26                  byte[] checkRes;
    9.27 -                if (c instanceof ZipHandler) {
    9.28 -                    checkRes = ((ZipHandler)c).findRes(res);
    9.29 +                if (c instanceof Bck2Brwsr.Resources) {
    9.30 +                    checkRes = readBytes((Bck2Brwsr.Resources)c, res);
    9.31                      if (checkRes != null && --skip < 0) {
    9.32                          return checkRes;
    9.33                      }
    9.34 @@ -116,4 +117,36 @@
    9.35  
    9.36      @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(null); return arr;")
    9.37      private static native Object enlargeArray(Object arr, int len);
    9.38 +    
    9.39 +    private static Bck2Brwsr.Resources toZip(String path) throws IOException {
    9.40 +        URL u = new URL(path);
    9.41 +        byte[] zipData = (byte[]) u.getContent(new Class[]{byte[].class});
    9.42 +        Bck2Brwsr.Resources r;
    9.43 +        try {
    9.44 +            Class<?> fastJar = Class.forName("org.apidesign.bck2brwsr.vmzip.ZipResources");
    9.45 +            return (Bck2Brwsr.Resources) fastJar.getConstructor(byte[].class).newInstance(zipData);
    9.46 +        } catch (Exception ex) {
    9.47 +            log("Reading JARs is only possible with enum.zip module included: " + ex.getMessage());
    9.48 +            ex.printStackTrace();
    9.49 +            throw new IOException(ex);
    9.50 +        }
    9.51 +    }
    9.52 +    
    9.53 +    private static byte[] readBytes(Bck2Brwsr.Resources r, String res) throws IOException {
    9.54 +        InputStream is = r.get(res);
    9.55 +        if (is == null) {
    9.56 +            return null;
    9.57 +        }
    9.58 +        byte[] arr = new byte[is.available()];
    9.59 +        int off = 0;
    9.60 +        for (;;) {
    9.61 +            int len = is.read(arr, off, arr.length - off);
    9.62 +            if (len == -1) {
    9.63 +                break;
    9.64 +            }
    9.65 +            off += len;
    9.66 +        }
    9.67 +        is.close();
    9.68 +        return arr;
    9.69 +    }
    9.70  }
    10.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ZipHandler.java	Wed May 07 17:24:29 2014 +0200
    10.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3 @@ -1,113 +0,0 @@
    10.4 -/**
    10.5 - * Back 2 Browser Bytecode Translator
    10.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    10.7 - *
    10.8 - * This program is free software: you can redistribute it and/or modify
    10.9 - * it under the terms of the GNU General Public License as published by
   10.10 - * the Free Software Foundation, version 2 of the License.
   10.11 - *
   10.12 - * This program is distributed in the hope that it will be useful,
   10.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10.15 - * GNU General Public License for more details.
   10.16 - *
   10.17 - * You should have received a copy of the GNU General Public License
   10.18 - * along with this program. Look for COPYING file in the top folder.
   10.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
   10.20 - */
   10.21 -package org.apidesign.vm4brwsr;
   10.22 -
   10.23 -import java.io.IOException;
   10.24 -import java.io.InputStream;
   10.25 -import java.net.URL;
   10.26 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
   10.27 -import org.apidesign.bck2brwsr.emul.zip.FastJar;
   10.28 -
   10.29 -/** Conversion from classpath to load function.
   10.30 - *
   10.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   10.32 - */
   10.33 -final class ZipHandler {
   10.34 -    private final FastJar fj;
   10.35 -
   10.36 -    private ZipHandler(String path, byte[] zipData) throws IOException {
   10.37 -        long bef = timeNow();
   10.38 -        fj = new FastJar(zipData);
   10.39 -        for (FastJar.Entry e : fj.list()) {
   10.40 -            putRes(e.name, e);
   10.41 -        }
   10.42 -        log("Iterating thru " + path + " took " + (timeNow() - bef) + "ms");
   10.43 -    }
   10.44 -    
   10.45 -    public static void init() {
   10.46 -    }
   10.47 -    @JavaScriptBody(args = { "arr" }, body = "return arr.length;")
   10.48 -    private static native int length(Object arr);
   10.49 -    @JavaScriptBody(args = { "arr", "index", "value" }, body = "arr[index] = value; return value;")
   10.50 -    private static native Object set(Object arr, int index, Object value);
   10.51 -    
   10.52 -    @JavaScriptBody(args = { "msg" }, body = "if (typeof console !== 'undefined') console.log(msg.toString());")
   10.53 -    private static native void log(String msg);
   10.54 -
   10.55 -    byte[] findRes(String res) throws IOException {
   10.56 -        Object arr = findResImpl(res);
   10.57 -        if (arr instanceof FastJar.Entry) {
   10.58 -            long bef = timeNow();
   10.59 -            InputStream zip = fj.getInputStream((FastJar.Entry)arr);
   10.60 -            arr = readFully(new byte[512], zip);
   10.61 -            putRes(res, arr);
   10.62 -            log("Reading " + res + " took " + (timeNow() - bef) + "ms");
   10.63 -        }
   10.64 -        return (byte[]) arr;
   10.65 -    }
   10.66 -
   10.67 -    @JavaScriptBody(args = { "res" }, body = "var r = this[res]; return r ? r : null;")
   10.68 -    private native Object findResImpl(String res);
   10.69 -
   10.70 -    @JavaScriptBody(args = { "res", "arr" }, body = "this[res] = arr;")
   10.71 -    private native void putRes(String res, Object arr);
   10.72 -    
   10.73 -    static ZipHandler toZip(String path) throws IOException {
   10.74 -        URL u = new URL(path);
   10.75 -        byte[] zipData = (byte[]) u.getContent(new Class[] { byte[].class });
   10.76 -        return new ZipHandler(path, zipData);
   10.77 -    }
   10.78 -
   10.79 -    @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(0);")
   10.80 -    private static native void enlargeBytes(byte[] arr, int len);
   10.81 -
   10.82 -    @JavaScriptBody(args = { "arr", "len" }, body = "arr.splice(len, arr.length - len);")
   10.83 -    private static native void sliceArray(byte[] arr, int len);
   10.84 -
   10.85 -    private static Object readFully(byte[] arr, InputStream zip) throws IOException {
   10.86 -        int offset = 0;
   10.87 -        for (;;) {
   10.88 -            int len = zip.read(arr, offset, arr.length - offset);
   10.89 -            if (len == -1) {
   10.90 -                break;
   10.91 -            }
   10.92 -            offset += len;
   10.93 -            if (offset == arr.length) {
   10.94 -                enlargeBytes(arr, arr.length + 4096);
   10.95 -            }
   10.96 -        }
   10.97 -        sliceArray(arr, offset);
   10.98 -        return arr;
   10.99 -    }
  10.100 -
  10.101 -    private static long timeNow() {
  10.102 -        double time = m();
  10.103 -        if (time >= 0) {
  10.104 -            return (long)time;
  10.105 -        }
  10.106 -        return org.apidesign.bck2brwsr.emul.lang.System.currentTimeMillis();
  10.107 -    }
  10.108 -    @JavaScriptBody(args = {}, body = 
  10.109 -        "if (typeof window.performance === 'undefined') return -1;\n"
  10.110 -      + "if (typeof window.performance.now === 'undefined') return -1;\n"
  10.111 -      + "return window.performance.now();"
  10.112 -    )
  10.113 -    private static native double m();
  10.114 -    
  10.115 -    
  10.116 -}