vm/src/main/java/org/apidesign/vm4brwsr/Zips.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 07 Feb 2013 13:41:56 +0100
branchemul
changeset 702 fa42b3d8cbbc
parent 690 8929a6558ae4
child 706 a48961ff3e6b
permissions -rw-r--r--
Recognizing Main-Class attribute, so initializing the VM is just about passing in correct classpath
     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.net.URL;
    23 import java.util.zip.ZipEntry;
    24 import java.util.zip.ZipInputStream;
    25 import org.apidesign.bck2brwsr.core.JavaScriptBody;
    26 
    27 /** Conversion from classpath to load function.
    28  *
    29  * @author Jaroslav Tulach <jtulach@netbeans.org>
    30  */
    31 final class Zips {
    32     private Zips() {
    33     }
    34     
    35     public static void init() {
    36     }
    37     
    38     public static byte[] loadFromCp(Object[] classpath, String res) throws Exception {
    39         for (int i = 0; i < classpath.length; i++) {
    40             Object c = classpath[i];
    41             if (c instanceof String) {
    42                 try {
    43                     String url = (String)c;
    44                     final Zips z = toZip(url);
    45                     c = classpath[i] = z;
    46                     final byte[] man = z.findRes("META-INF/MANIFEST.MF");
    47                     if (man != null) {
    48                         String mainClass = processClassPathAttr(man, url, classpath);
    49                         if (mainClass != null) {
    50                             Class.forName(mainClass);
    51                         }
    52                     }
    53                 } catch (Exception ex) {
    54                     classpath[i] = ex;
    55                     throw ex;
    56                 }
    57             }
    58             if (res != null && c instanceof Zips) {
    59                 Object checkRes = ((Zips)c).findRes(res);
    60                 if (checkRes instanceof byte[]) {
    61                     return (byte[])checkRes;
    62                 }
    63             }
    64         }
    65         return null;
    66     }
    67 
    68     @JavaScriptBody(args = { "res" }, body = "var r = this[res]; return r ? r : null;")
    69     private native byte[] findRes(String res);
    70 
    71     @JavaScriptBody(args = { "res", "arr" }, body = "this[res] = arr;")
    72     private native void putRes(String res, byte[] arr);
    73     
    74     private static Zips toZip(String path) throws IOException {
    75         URL u = new URL(path);
    76         ZipInputStream zip = new ZipInputStream(u.openStream());
    77         Zips z = new Zips();
    78         for (;;) {
    79             ZipEntry entry = zip.getNextEntry();
    80             if (entry == null) {
    81                 break;
    82             }
    83             byte[] arr = new byte[4096];
    84             int offset = 0;
    85             for (;;) {
    86                 int len = zip.read(arr, offset, arr.length - offset);
    87                 if (len == -1) {
    88                     break;
    89                 }
    90                 offset += len;
    91                 if (offset == arr.length) {
    92                     enlargeArray(arr, arr.length + 4096);
    93                 }
    94             }
    95             sliceArray(arr, offset);
    96             z.putRes(entry.getName(), arr);
    97         }
    98         return z;
    99     }
   100 
   101     private static String processClassPathAttr(final byte[] man, String url, Object[] classpath) throws IOException {
   102         try (ParseMan is = new ParseMan(new ByteArrayInputStream(man))) {
   103             String cp = is.toString();
   104             if (cp != null) {
   105                 cp = cp.trim();
   106                 for (int p = 0; p < cp.length();) {
   107                     int n = cp.indexOf(' ', p);
   108                     if (n == -1) {
   109                         n = cp.length();
   110                     }
   111                     String el = cp.substring(p, n);
   112                     URL u = new URL(new URL(url), el);
   113                     classpath = addToArray(classpath, u.toString());
   114                     p = n + 1;
   115                 }
   116             }
   117             return is.getMainClass();
   118         }
   119     }
   120 
   121     private static Object[] addToArray(Object[] arr, String value) {
   122         final int last = arr.length;
   123         Object[] ret = enlargeArray(arr, last + 1);
   124         ret[last] = value;
   125         return ret;
   126     }
   127 
   128     @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(null); return arr;throw('Arr: ' + arr);")
   129     private static native Object[] enlargeArray(Object[] arr, int len);
   130     @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(0);")
   131     private static native void enlargeArray(byte[] arr, int len);
   132 
   133     @JavaScriptBody(args = { "arr", "len" }, body = "arr.splice(len, arr.length - len);")
   134     private static native void sliceArray(byte[] arr, int len);
   135     
   136     
   137 }