vm/src/main/java/org/apidesign/vm4brwsr/Zips.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Wed, 06 Feb 2013 17:22:14 +0100
branchemul
changeset 690 8929a6558ae4
parent 672 add357fd6c5c
child 702 fa42b3d8cbbc
permissions -rw-r--r--
Class-Path elements are separated by spaces
     1 /**
     2  * Back 2 Browser Bytecode Translator
     3  * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4  *
     5  * This program is free software: you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation, version 2 of the License.
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program. Look for COPYING file in the top folder.
    16  * If not, see http://opensource.org/licenses/GPL-2.0.
    17  */
    18 package org.apidesign.vm4brwsr;
    19 
    20 import java.io.ByteArrayInputStream;
    21 import java.io.IOException;
    22 import java.io.InputStream;
    23 import java.net.URL;
    24 import java.util.zip.ZipEntry;
    25 import java.util.zip.ZipInputStream;
    26 import org.apidesign.bck2brwsr.core.JavaScriptBody;
    27 
    28 /** Conversion from classpath to load function.
    29  *
    30  * @author Jaroslav Tulach <jtulach@netbeans.org>
    31  */
    32 final class Zips {
    33     private Zips() {
    34     }
    35     
    36     public static void init() {
    37     }
    38     
    39     public static byte[] loadFromCp(Object[] classpath, String res) {
    40         for (int i = 0; i < classpath.length; i++) {
    41             Object c = classpath[i];
    42             if (c instanceof String) {
    43                 try {
    44                     String url = (String)c;
    45                     final Zips z = toZip(url);
    46                     c = classpath[i] = z;
    47                     final byte[] man = z.findRes("META-INF/MANIFEST.MF");
    48                     if (man != null) {
    49                         processClassPathAttr(man, url, classpath);
    50                     }
    51                 } catch (IOException ex) {
    52                     classpath[i] = ex;
    53                 }
    54             }
    55             if (c instanceof Zips) {
    56                 Object checkRes = ((Zips)c).findRes(res);
    57                 if (checkRes instanceof byte[]) {
    58                     return (byte[])checkRes;
    59                 }
    60             }
    61         }
    62         return null;
    63     }
    64 
    65     @JavaScriptBody(args = { "res" }, body = "var r = this[res]; return r ? r : null;")
    66     private native byte[] findRes(String res);
    67 
    68     @JavaScriptBody(args = { "res", "arr" }, body = "this[res] = arr;")
    69     private native void putRes(String res, byte[] arr);
    70     
    71     private static Zips toZip(String path) throws IOException {
    72         URL u = new URL(path);
    73         ZipInputStream zip = new ZipInputStream(u.openStream());
    74         Zips z = new Zips();
    75         for (;;) {
    76             ZipEntry entry = zip.getNextEntry();
    77             if (entry == null) {
    78                 break;
    79             }
    80             byte[] arr = new byte[4096];
    81             int offset = 0;
    82             for (;;) {
    83                 int len = zip.read(arr, offset, arr.length - offset);
    84                 if (len == -1) {
    85                     break;
    86                 }
    87                 offset += len;
    88                 if (offset == arr.length) {
    89                     enlargeArray(arr, arr.length + 4096);
    90                 }
    91             }
    92             sliceArray(arr, offset);
    93             z.putRes(entry.getName(), arr);
    94         }
    95         return z;
    96     }
    97 
    98     private static void processClassPathAttr(final byte[] man, String url, Object[] classpath) throws IOException {
    99         try (InputStream is = initIS(new ByteArrayInputStream(man))) {
   100             String cp = is.toString();
   101             if (cp == null) {
   102                 return;
   103             }
   104             cp = cp.trim();
   105             for (int p = 0; p < cp.length();) {
   106                 int n = cp.indexOf(' ', p);
   107                 if (n == -1) {
   108                     n = cp.length();
   109                 }
   110                 String el = cp.substring(p, n);
   111                 URL u = new URL(new URL(url), el);
   112                 classpath = addToArray(classpath, u.toString());
   113                 p = n + 1;
   114             }
   115         }
   116     }
   117 
   118     private static InputStream initIS(InputStream is) throws IOException {
   119         return new ParseCPAttr(is);
   120     }
   121     
   122     private static Object[] addToArray(Object[] arr, String value) {
   123         final int last = arr.length;
   124         Object[] ret = enlargeArray(arr, last + 1);
   125         ret[last] = value;
   126         return ret;
   127     }
   128 
   129     @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(null); return arr;throw('Arr: ' + arr);")
   130     private static native Object[] enlargeArray(Object[] arr, int len);
   131     @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(0);")
   132     private static native void enlargeArray(byte[] arr, int len);
   133 
   134     @JavaScriptBody(args = { "arr", "len" }, body = "arr.splice(len, arr.length - len);")
   135     private static native void sliceArray(byte[] arr, int len);
   136     
   137     
   138 }