Flexible composition of classpath. One can either specify a URL or a load function
1.1 --- a/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml Tue Feb 12 16:46:13 2013 +0100
1.2 +++ b/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml Tue Feb 12 23:30:01 2013 +0100
1.3 @@ -79,9 +79,7 @@
1.4 <div data-bind="text: displayPreview"></div>
1.5 <script src="bck2brwsr.js"/>
1.6 <script>
1.7 - var vm = bck2brwsr(
1.8 - [ 'demo.static.calculator-0.3-SNAPSHOT.jar' ]
1.9 - );
1.10 + var vm = bck2brwsr('demo.static.calculator-0.3-SNAPSHOT.jar');
1.11 </script>
1.12 </body>
1.13 </html>
2.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Tue Feb 12 16:46:13 2013 +0100
2.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Tue Feb 12 23:30:01 2013 +0100
2.3 @@ -40,6 +40,16 @@
2.4 * In this scenario, when a request for an unknown class is made, the loader
2.5 * function is asked for its byte code and the system dynamically transforms
2.6 * it to JavaScript.
2.7 + * <p>
2.8 + * Instead of a loader function, one can also provide a URL to a JAR file.
2.9 + * The <code>bck2brwsr</code> system will do its best to download the file
2.10 + * and provide loader function for it automatically.
2.11 + * <p>
2.12 + * One can provide as many loader functions and JAR URL references as necessary.
2.13 + * Then the initialization code would look like:<pre>
2.14 + * var vm = bck2brwsr(url1, url2, fnctn1, url3, functn2);
2.15 + * </pre>
2.16 + * The provided URLs and loader functions will be consulted one by one.
2.17 *
2.18 * @author Jaroslav Tulach <jtulach@netbeans.org>
2.19 */
3.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Tue Feb 12 16:46:13 2013 +0100
3.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Tue Feb 12 23:30:01 2013 +0100
3.3 @@ -119,36 +119,28 @@
3.4 " return vm;\n"
3.5 + " };\n"
3.6 + " global.bck2brwsr = function() {\n"
3.7 - + " var args = arguments;\n"
3.8 + + " var args = Array.prototype.slice.apply(arguments);\n"
3.9 + " var vm = fillInVMSkeleton({});\n"
3.10 + " var loader = {};\n"
3.11 - + " var init = null;\n"
3.12 + " loader.vm = vm;\n"
3.13 - + " if (args.length == 1 && typeof args[0] !== 'function') {;\n"
3.14 - + " var classpath = args[0];\n"
3.15 - + " init = args[0] = function(name) {\n"
3.16 - + " return vm.org_apidesign_vm4brwsr_Zips(false).loadFromCp___3B_3Ljava_lang_Object_2Ljava_lang_String_2(classpath, name);\n"
3.17 - + " };\n"
3.18 - + " };\n"
3.19 + " loader.loadClass = function(name) {\n"
3.20 + " var attr = name.replace__Ljava_lang_String_2CC('.','_');\n"
3.21 + " var fn = vm[attr];\n"
3.22 + " if (fn) return fn(false);\n"
3.23 - + " if (!args[0]) throw 'bck2brwsr initialized without loader function, cannot load ' + name;\n"
3.24 + " return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
3.25 + " load__Ljava_lang_Object_2Ljava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n"
3.26 + " }\n"
3.27 - + " if (args[0]) {\n"
3.28 - + " if (vm.loadClass) {\n"
3.29 - + " throw 'Cannot initialize the bck2brwsr VM twice!';\n"
3.30 - + " }\n"
3.31 - + " vm.loadClass = loader.loadClass;\n"
3.32 - + " vm.loadBytes = function(name) {\n"
3.33 - + " if (!args[0]) throw 'bck2brwsr initialized without loader function, cannot load ' + name;\n"
3.34 - + " return args[0](name);\n"
3.35 - + " }\n"
3.36 + + " if (vm.loadClass) {\n"
3.37 + + " throw 'Cannot initialize the bck2brwsr VM twice!';\n"
3.38 + " }\n"
3.39 - + " if (init) init(null);\n"
3.40 + + " vm.loadClass = loader.loadClass;\n"
3.41 + + " vm.loadBytes = function(name) {\n"
3.42 + + " return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
3.43 + + " loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n"
3.44 + + " }\n"
3.45 + + " vm.java_lang_reflect_Array(false);\n"
3.46 + + " vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
3.47 + + " loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, null, args);\n"
3.48 + " return loader;\n"
3.49 + " };\n");
3.50 out.append("}(this));");
4.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java Tue Feb 12 16:46:13 2013 +0100
4.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java Tue Feb 12 23:30:01 2013 +0100
4.3 @@ -20,6 +20,7 @@
4.4 import java.io.ByteArrayInputStream;
4.5 import java.io.IOException;
4.6 import java.io.InputStream;
4.7 +import java.lang.reflect.Array;
4.8 import org.apidesign.bck2brwsr.core.JavaScriptBody;
4.9
4.10 /**
4.11 @@ -38,23 +39,19 @@
4.12 static void init() {
4.13 }
4.14
4.15 - @JavaScriptBody(args={"l", "res", "args" }, body = ""
4.16 - + "\ntry {"
4.17 - + "\n return args[0](res.toString());"
4.18 - + "\n} catch (x) {"
4.19 - + "\n throw Object.getOwnPropertyNames(l.vm).toString() + x.toString();"
4.20 - + "\n}")
4.21 - private static native byte[] read(Object l, String res, Object[] args);
4.22 -
4.23 static Object load(Object loader, String name, Object[] arguments)
4.24 throws IOException, ClassNotFoundException {
4.25 return new VMLazy(loader, arguments).load(name, false);
4.26 }
4.27
4.28 + static byte[] loadBytes(Object loader, String name, Object[] arguments) throws Exception {
4.29 + return Zips.loadFromCp(arguments, name);
4.30 + }
4.31 +
4.32 private Object load(String name, boolean instance)
4.33 throws IOException, ClassNotFoundException {
4.34 String res = name.replace('.', '/') + ".class";
4.35 - byte[] arr = read(loader, res, args);
4.36 + byte[] arr = Zips.loadFromCp(args, res);
4.37 if (arr == null) {
4.38 throw new ClassNotFoundException(name);
4.39 }
5.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/Zips.java Tue Feb 12 16:46:13 2013 +0100
5.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Zips.java Tue Feb 12 23:30:01 2013 +0100
5.3 @@ -42,15 +42,22 @@
5.4
5.5 public static void init() {
5.6 }
5.7 + @JavaScriptBody(args = { "arr" }, body = "return arr.length;")
5.8 + private static native int length(Object arr);
5.9 + @JavaScriptBody(args = { "arr", "index" }, body = "return arr[index];")
5.10 + private static native Object at(Object arr, int index);
5.11 + @JavaScriptBody(args = { "arr", "index", "value" }, body = "arr[index] = value; return value;")
5.12 + private static native Object set(Object arr, int index, Object value);
5.13
5.14 - public static byte[] loadFromCp(Object[] classpath, String res) throws Exception {
5.15 - for (int i = 0; i < classpath.length; i++) {
5.16 - Object c = classpath[i];
5.17 + public static byte[] loadFromCp(Object classpath, String res)
5.18 + throws IOException, ClassNotFoundException {
5.19 + for (int i = 0; i < length(classpath); i++) {
5.20 + Object c = at(classpath, i);
5.21 if (c instanceof String) {
5.22 try {
5.23 String url = (String)c;
5.24 final Zips z = toZip(url);
5.25 - c = classpath[i] = z;
5.26 + c = set(classpath, i, z);
5.27 final byte[] man = z.findRes("META-INF/MANIFEST.MF");
5.28 if (man != null) {
5.29 String mainClass = processClassPathAttr(man, url, classpath);
5.30 @@ -58,21 +65,32 @@
5.31 Class.forName(mainClass);
5.32 }
5.33 }
5.34 - } catch (Exception ex) {
5.35 - classpath[i] = ex;
5.36 + } catch (IOException | ClassNotFoundException ex) {
5.37 + set(classpath, i, ex);
5.38 throw ex;
5.39 }
5.40 }
5.41 - if (res != null && c instanceof Zips) {
5.42 - Object checkRes = ((Zips)c).findRes(res);
5.43 - if (checkRes instanceof byte[]) {
5.44 - return (byte[])checkRes;
5.45 + if (res != null) {
5.46 + byte[] checkRes;
5.47 + if (c instanceof Zips) {
5.48 + checkRes = ((Zips)c).findRes(res);
5.49 + } else {
5.50 + checkRes = callFunction(c, res);
5.51 + }
5.52 + if (checkRes != null) {
5.53 + return checkRes;
5.54 }
5.55 }
5.56 }
5.57 return null;
5.58 }
5.59
5.60 + @JavaScriptBody(args = { "fn", "res" }, body =
5.61 + "if (typeof fn === 'function') return fn(res);\n"
5.62 + + "return null;"
5.63 + )
5.64 + private static native byte[] callFunction(Object fn, String res);
5.65 +
5.66 @JavaScriptBody(args = { "msg" }, body = "console.log(msg.toString());")
5.67 private static native void log(String msg);
5.68
5.69 @@ -100,7 +118,7 @@
5.70 return new Zips(path, zipData);
5.71 }
5.72
5.73 - private static String processClassPathAttr(final byte[] man, String url, Object[] classpath) throws IOException {
5.74 + private static String processClassPathAttr(final byte[] man, String url, Object classpath) throws IOException {
5.75 try (ParseMan is = new ParseMan(new ByteArrayInputStream(man))) {
5.76 String cp = is.toString();
5.77 if (cp != null) {
5.78 @@ -120,17 +138,17 @@
5.79 }
5.80 }
5.81
5.82 - private static Object[] addToArray(Object[] arr, String value) {
5.83 - final int last = arr.length;
5.84 - Object[] ret = enlargeArray(arr, last + 1);
5.85 - ret[last] = value;
5.86 + private static Object addToArray(Object arr, String value) {
5.87 + final int last = length(arr);
5.88 + Object ret = enlargeArray(arr, last + 1);
5.89 + set(ret, last, value);
5.90 return ret;
5.91 }
5.92
5.93 - @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(null); return arr;throw('Arr: ' + arr);")
5.94 - private static native Object[] enlargeArray(Object[] arr, int len);
5.95 + @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(null); return arr;")
5.96 + private static native Object enlargeArray(Object arr, int len);
5.97 @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(0);")
5.98 - private static native void enlargeArray(byte[] arr, int len);
5.99 + private static native void enlargeBytes(byte[] arr, int len);
5.100
5.101 @JavaScriptBody(args = { "arr", "len" }, body = "arr.splice(len, arr.length - len);")
5.102 private static native void sliceArray(byte[] arr, int len);
5.103 @@ -144,7 +162,7 @@
5.104 }
5.105 offset += len;
5.106 if (offset == arr.length) {
5.107 - enlargeArray(arr, arr.length + 4096);
5.108 + enlargeBytes(arr, arr.length + 4096);
5.109 }
5.110 }
5.111 sliceArray(arr, offset);
6.1 --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java Tue Feb 12 16:46:13 2013 +0100
6.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java Tue Feb 12 23:30:01 2013 +0100
6.3 @@ -54,7 +54,7 @@
6.4 }
6.5
6.6 @JavaScriptBody(args = { "res", "path" }, body =
6.7 - "var myvm = bck2brwsr(path);\n"
6.8 + "var myvm = bck2brwsr.apply(null, path);\n"
6.9 + "var cls = myvm.loadClass('java.lang.String');\n"
6.10 + "return cls.getClass__Ljava_lang_Class_2().getResourceAsStream__Ljava_io_InputStream_2Ljava_lang_String_2(res);\n"
6.11 )