rt/emul/zip/src/main/java/org/apidesign/bck2brwsr/vmzip/ZipResources.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Fri, 09 May 2014 08:37:20 +0200
branchclosure
changeset 1551 0002739b6d1f
parent 1550 rt/vm/src/main/java/org/apidesign/vm4brwsr/ZipHandler.java@cb9e273dfd51
child 1555 71e68f7ed23f
permissions -rw-r--r--
Moving Zip tests into right locations
jaroslav@644
     1
/**
jaroslav@644
     2
 * Back 2 Browser Bytecode Translator
jaroslav@644
     3
 * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
jaroslav@644
     4
 *
jaroslav@644
     5
 * This program is free software: you can redistribute it and/or modify
jaroslav@644
     6
 * it under the terms of the GNU General Public License as published by
jaroslav@644
     7
 * the Free Software Foundation, version 2 of the License.
jaroslav@644
     8
 *
jaroslav@644
     9
 * This program is distributed in the hope that it will be useful,
jaroslav@644
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
jaroslav@644
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
jaroslav@644
    12
 * GNU General Public License for more details.
jaroslav@644
    13
 *
jaroslav@644
    14
 * You should have received a copy of the GNU General Public License
jaroslav@644
    15
 * along with this program. Look for COPYING file in the top folder.
jaroslav@644
    16
 * If not, see http://opensource.org/licenses/GPL-2.0.
jaroslav@644
    17
 */
jaroslav@1551
    18
package org.apidesign.bck2brwsr.vmzip;
jaroslav@644
    19
jaroslav@1551
    20
import java.io.ByteArrayInputStream;
jaroslav@644
    21
import java.io.IOException;
jaroslav@706
    22
import java.io.InputStream;
jaroslav@1551
    23
import org.apidesign.bck2brwsr.core.Exported;
jaroslav@644
    24
import org.apidesign.bck2brwsr.core.JavaScriptBody;
jaroslav@706
    25
import org.apidesign.bck2brwsr.emul.zip.FastJar;
jaroslav@1551
    26
import org.apidesign.vm4brwsr.Bck2Brwsr;
jaroslav@644
    27
jaroslav@644
    28
/** Conversion from classpath to load function.
jaroslav@644
    29
 *
jaroslav@644
    30
 * @author Jaroslav Tulach <jtulach@netbeans.org>
jaroslav@644
    31
 */
jaroslav@1551
    32
@Exported
jaroslav@1551
    33
public final class ZipResources implements Bck2Brwsr.Resources {
jaroslav@706
    34
    private final FastJar fj;
jaroslav@706
    35
jaroslav@1551
    36
    @Exported
jaroslav@1551
    37
    public ZipResources(byte[] zipData) throws IOException {
jaroslav@1551
    38
//        long bef = timeNow();
jaroslav@706
    39
        fj = new FastJar(zipData);
jaroslav@706
    40
        for (FastJar.Entry e : fj.list()) {
jaroslav@706
    41
            putRes(e.name, e);
jaroslav@706
    42
        }
jaroslav@1551
    43
//        log("Iterating thru " + path + " took " + (timeNow() - bef) + "ms");
jaroslav@644
    44
    }
jaroslav@644
    45
    
jaroslav@729
    46
    @JavaScriptBody(args = { "arr" }, body = "return arr.length;")
jaroslav@729
    47
    private static native int length(Object arr);
jaroslav@729
    48
    @JavaScriptBody(args = { "arr", "index", "value" }, body = "arr[index] = value; return value;")
jaroslav@729
    49
    private static native Object set(Object arr, int index, Object value);
jaroslav@644
    50
    
jaroslav@1358
    51
    @JavaScriptBody(args = { "msg" }, body = "if (typeof console !== 'undefined') console.log(msg.toString());")
jaroslav@706
    52
    private static native void log(String msg);
jaroslav@706
    53
jaroslav@1551
    54
    private byte[] findRes(String res) throws IOException {
jaroslav@706
    55
        Object arr = findResImpl(res);
jaroslav@706
    56
        if (arr instanceof FastJar.Entry) {
jaroslav@715
    57
            long bef = timeNow();
jaroslav@706
    58
            InputStream zip = fj.getInputStream((FastJar.Entry)arr);
jaroslav@706
    59
            arr = readFully(new byte[512], zip);
jaroslav@706
    60
            putRes(res, arr);
jaroslav@715
    61
            log("Reading " + res + " took " + (timeNow() - bef) + "ms");
jaroslav@706
    62
        }
jaroslav@706
    63
        return (byte[]) arr;
jaroslav@706
    64
    }
jaroslav@644
    65
jaroslav@1551
    66
    @Override
jaroslav@1551
    67
    public InputStream get(String resource) throws IOException {
jaroslav@1551
    68
        byte[] arr = findRes(resource);
jaroslav@1551
    69
        return arr == null ? null : new ByteArrayInputStream(arr);
jaroslav@1551
    70
    }
jaroslav@1551
    71
jaroslav@644
    72
    @JavaScriptBody(args = { "res" }, body = "var r = this[res]; return r ? r : null;")
jaroslav@706
    73
    private native Object findResImpl(String res);
jaroslav@644
    74
jaroslav@644
    75
    @JavaScriptBody(args = { "res", "arr" }, body = "this[res] = arr;")
jaroslav@706
    76
    private native void putRes(String res, Object arr);
jaroslav@644
    77
    
jaroslav@644
    78
    @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(0);")
jaroslav@729
    79
    private static native void enlargeBytes(byte[] arr, int len);
jaroslav@644
    80
jaroslav@644
    81
    @JavaScriptBody(args = { "arr", "len" }, body = "arr.splice(len, arr.length - len);")
jaroslav@644
    82
    private static native void sliceArray(byte[] arr, int len);
jaroslav@706
    83
jaroslav@706
    84
    private static Object readFully(byte[] arr, InputStream zip) throws IOException {
jaroslav@706
    85
        int offset = 0;
jaroslav@706
    86
        for (;;) {
jaroslav@706
    87
            int len = zip.read(arr, offset, arr.length - offset);
jaroslav@706
    88
            if (len == -1) {
jaroslav@706
    89
                break;
jaroslav@706
    90
            }
jaroslav@706
    91
            offset += len;
jaroslav@706
    92
            if (offset == arr.length) {
jaroslav@729
    93
                enlargeBytes(arr, arr.length + 4096);
jaroslav@706
    94
            }
jaroslav@706
    95
        }
jaroslav@706
    96
        sliceArray(arr, offset);
jaroslav@706
    97
        return arr;
jaroslav@706
    98
    }
jaroslav@706
    99
jaroslav@715
   100
    private static long timeNow() {
jaroslav@715
   101
        double time = m();
jaroslav@715
   102
        if (time >= 0) {
jaroslav@715
   103
            return (long)time;
jaroslav@715
   104
        }
jaroslav@715
   105
        return org.apidesign.bck2brwsr.emul.lang.System.currentTimeMillis();
jaroslav@706
   106
    }
jaroslav@715
   107
    @JavaScriptBody(args = {}, body = 
jaroslav@715
   108
        "if (typeof window.performance === 'undefined') return -1;\n"
jaroslav@715
   109
      + "if (typeof window.performance.now === 'undefined') return -1;\n"
jaroslav@715
   110
      + "return window.performance.now();"
jaroslav@715
   111
    )
jaroslav@706
   112
    private static native double m();
jaroslav@1551
   113
jaroslav@644
   114
    
jaroslav@644
   115
}