# HG changeset patch # User Jaroslav Tulach # Date 1360708201 -3600 # Node ID 1ee59fe94653392a407811327b3c62654108894c # Parent 7572022945a0576a4d2e71ec886cbf4b4e98dd21 Flexible composition of classpath. One can either specify a URL or a load function diff -r 7572022945a0 -r 1ee59fe94653 javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml --- a/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml Tue Feb 12 16:46:13 2013 +0100 +++ b/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml Tue Feb 12 23:30:01 2013 +0100 @@ -79,9 +79,7 @@
diff -r 7572022945a0 -r 1ee59fe94653 vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java --- a/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Tue Feb 12 16:46:13 2013 +0100 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Tue Feb 12 23:30:01 2013 +0100 @@ -40,6 +40,16 @@ * In this scenario, when a request for an unknown class is made, the loader * function is asked for its byte code and the system dynamically transforms * it to JavaScript. + *

+ * Instead of a loader function, one can also provide a URL to a JAR file. + * The bck2brwsr system will do its best to download the file + * and provide loader function for it automatically. + *

+ * One can provide as many loader functions and JAR URL references as necessary. + * Then the initialization code would look like:

+ * var vm = bck2brwsr(url1, url2, fnctn1, url3, functn2);
+ * 
+ * The provided URLs and loader functions will be consulted one by one. * * @author Jaroslav Tulach */ diff -r 7572022945a0 -r 1ee59fe94653 vm/src/main/java/org/apidesign/vm4brwsr/VM.java --- a/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Tue Feb 12 16:46:13 2013 +0100 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Tue Feb 12 23:30:01 2013 +0100 @@ -119,36 +119,28 @@ " return vm;\n" + " };\n" + " global.bck2brwsr = function() {\n" - + " var args = arguments;\n" + + " var args = Array.prototype.slice.apply(arguments);\n" + " var vm = fillInVMSkeleton({});\n" + " var loader = {};\n" - + " var init = null;\n" + " loader.vm = vm;\n" - + " if (args.length == 1 && typeof args[0] !== 'function') {;\n" - + " var classpath = args[0];\n" - + " init = args[0] = function(name) {\n" - + " return vm.org_apidesign_vm4brwsr_Zips(false).loadFromCp___3B_3Ljava_lang_Object_2Ljava_lang_String_2(classpath, name);\n" - + " };\n" - + " };\n" + " loader.loadClass = function(name) {\n" + " var attr = name.replace__Ljava_lang_String_2CC('.','_');\n" + " var fn = vm[attr];\n" + " if (fn) return fn(false);\n" - + " if (!args[0]) throw 'bck2brwsr initialized without loader function, cannot load ' + name;\n" + " return vm.org_apidesign_vm4brwsr_VMLazy(false).\n" + " load__Ljava_lang_Object_2Ljava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n" + " }\n" - + " if (args[0]) {\n" - + " if (vm.loadClass) {\n" - + " throw 'Cannot initialize the bck2brwsr VM twice!';\n" - + " }\n" - + " vm.loadClass = loader.loadClass;\n" - + " vm.loadBytes = function(name) {\n" - + " if (!args[0]) throw 'bck2brwsr initialized without loader function, cannot load ' + name;\n" - + " return args[0](name);\n" - + " }\n" + + " if (vm.loadClass) {\n" + + " throw 'Cannot initialize the bck2brwsr VM twice!';\n" + " }\n" - + " if (init) init(null);\n" + + " vm.loadClass = loader.loadClass;\n" + + " vm.loadBytes = function(name) {\n" + + " return vm.org_apidesign_vm4brwsr_VMLazy(false).\n" + + " loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n" + + " }\n" + + " vm.java_lang_reflect_Array(false);\n" + + " vm.org_apidesign_vm4brwsr_VMLazy(false).\n" + + " loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, null, args);\n" + " return loader;\n" + " };\n"); out.append("}(this));"); diff -r 7572022945a0 -r 1ee59fe94653 vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java --- a/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java Tue Feb 12 16:46:13 2013 +0100 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java Tue Feb 12 23:30:01 2013 +0100 @@ -20,6 +20,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.lang.reflect.Array; import org.apidesign.bck2brwsr.core.JavaScriptBody; /** @@ -38,23 +39,19 @@ static void init() { } - @JavaScriptBody(args={"l", "res", "args" }, body = "" - + "\ntry {" - + "\n return args[0](res.toString());" - + "\n} catch (x) {" - + "\n throw Object.getOwnPropertyNames(l.vm).toString() + x.toString();" - + "\n}") - private static native byte[] read(Object l, String res, Object[] args); - static Object load(Object loader, String name, Object[] arguments) throws IOException, ClassNotFoundException { return new VMLazy(loader, arguments).load(name, false); } + static byte[] loadBytes(Object loader, String name, Object[] arguments) throws Exception { + return Zips.loadFromCp(arguments, name); + } + private Object load(String name, boolean instance) throws IOException, ClassNotFoundException { String res = name.replace('.', '/') + ".class"; - byte[] arr = read(loader, res, args); + byte[] arr = Zips.loadFromCp(args, res); if (arr == null) { throw new ClassNotFoundException(name); } diff -r 7572022945a0 -r 1ee59fe94653 vm/src/main/java/org/apidesign/vm4brwsr/Zips.java --- a/vm/src/main/java/org/apidesign/vm4brwsr/Zips.java Tue Feb 12 16:46:13 2013 +0100 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Zips.java Tue Feb 12 23:30:01 2013 +0100 @@ -42,15 +42,22 @@ public static void init() { } + @JavaScriptBody(args = { "arr" }, body = "return arr.length;") + private static native int length(Object arr); + @JavaScriptBody(args = { "arr", "index" }, body = "return arr[index];") + private static native Object at(Object arr, int index); + @JavaScriptBody(args = { "arr", "index", "value" }, body = "arr[index] = value; return value;") + private static native Object set(Object arr, int index, Object value); - public static byte[] loadFromCp(Object[] classpath, String res) throws Exception { - for (int i = 0; i < classpath.length; i++) { - Object c = classpath[i]; + public static byte[] loadFromCp(Object classpath, String res) + throws IOException, ClassNotFoundException { + for (int i = 0; i < length(classpath); i++) { + Object c = at(classpath, i); if (c instanceof String) { try { String url = (String)c; final Zips z = toZip(url); - c = classpath[i] = z; + c = set(classpath, i, z); final byte[] man = z.findRes("META-INF/MANIFEST.MF"); if (man != null) { String mainClass = processClassPathAttr(man, url, classpath); @@ -58,21 +65,32 @@ Class.forName(mainClass); } } - } catch (Exception ex) { - classpath[i] = ex; + } catch (IOException | ClassNotFoundException ex) { + set(classpath, i, ex); throw ex; } } - if (res != null && c instanceof Zips) { - Object checkRes = ((Zips)c).findRes(res); - if (checkRes instanceof byte[]) { - return (byte[])checkRes; + if (res != null) { + byte[] checkRes; + if (c instanceof Zips) { + checkRes = ((Zips)c).findRes(res); + } else { + checkRes = callFunction(c, res); + } + if (checkRes != null) { + return checkRes; } } } return null; } + @JavaScriptBody(args = { "fn", "res" }, body = + "if (typeof fn === 'function') return fn(res);\n" + + "return null;" + ) + private static native byte[] callFunction(Object fn, String res); + @JavaScriptBody(args = { "msg" }, body = "console.log(msg.toString());") private static native void log(String msg); @@ -100,7 +118,7 @@ return new Zips(path, zipData); } - private static String processClassPathAttr(final byte[] man, String url, Object[] classpath) throws IOException { + private static String processClassPathAttr(final byte[] man, String url, Object classpath) throws IOException { try (ParseMan is = new ParseMan(new ByteArrayInputStream(man))) { String cp = is.toString(); if (cp != null) { @@ -120,17 +138,17 @@ } } - private static Object[] addToArray(Object[] arr, String value) { - final int last = arr.length; - Object[] ret = enlargeArray(arr, last + 1); - ret[last] = value; + private static Object addToArray(Object arr, String value) { + final int last = length(arr); + Object ret = enlargeArray(arr, last + 1); + set(ret, last, value); return ret; } - @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(null); return arr;throw('Arr: ' + arr);") - private static native Object[] enlargeArray(Object[] arr, int len); + @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(null); return arr;") + private static native Object enlargeArray(Object arr, int len); @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(0);") - private static native void enlargeArray(byte[] arr, int len); + private static native void enlargeBytes(byte[] arr, int len); @JavaScriptBody(args = { "arr", "len" }, body = "arr.splice(len, arr.length - len);") private static native void sliceArray(byte[] arr, int len); @@ -144,7 +162,7 @@ } offset += len; if (offset == arr.length) { - enlargeArray(arr, arr.length + 4096); + enlargeBytes(arr, arr.length + 4096); } } sliceArray(arr, offset); diff -r 7572022945a0 -r 1ee59fe94653 vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java Tue Feb 12 16:46:13 2013 +0100 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java Tue Feb 12 23:30:01 2013 +0100 @@ -54,7 +54,7 @@ } @JavaScriptBody(args = { "res", "path" }, body = - "var myvm = bck2brwsr(path);\n" + "var myvm = bck2brwsr.apply(null, path);\n" + "var cls = myvm.loadClass('java.lang.String');\n" + "return cls.getClass__Ljava_lang_Class_2().getResourceAsStream__Ljava_io_InputStream_2Ljava_lang_String_2(res);\n" )