# HG changeset patch # User Lubomir Nerad # Date 1366899468 -7200 # Node ID a6bacea2518f331fbc126c2f69f41cba5f8fed6e # Parent c2386b2f53d00dd8f341a14554f2de4bc4d3d03e Initial structure for extension modules diff -r c2386b2f53d0 -r a6bacea2518f dew/src/main/java/org/apidesign/bck2brwsr/dew/Dew.java --- a/dew/src/main/java/org/apidesign/bck2brwsr/dew/Dew.java Mon Apr 15 15:30:53 2013 +0200 +++ b/dew/src/main/java/org/apidesign/bck2brwsr/dew/Dew.java Thu Apr 25 16:17:48 2013 +0200 @@ -135,4 +135,9 @@ byte[] arr = data == null ? null : data.get(r); return arr == null ? null : new ByteArrayInputStream(arr); } + + @Override + public String getModule(String resource) throws IOException { + return null; + } } diff -r c2386b2f53d0 -r a6bacea2518f dew/src/main/java/org/apidesign/bck2brwsr/dew/DewLauncher.java --- a/dew/src/main/java/org/apidesign/bck2brwsr/dew/DewLauncher.java Mon Apr 15 15:30:53 2013 +0200 +++ b/dew/src/main/java/org/apidesign/bck2brwsr/dew/DewLauncher.java Thu Apr 25 16:17:48 2013 +0200 @@ -122,6 +122,11 @@ } throw new IOException("Can't find " + resource); } + + @Override + public String getModule(String resource) throws IOException { + return null; + } } private static class VM extends HttpHandler { diff -r c2386b2f53d0 -r a6bacea2518f rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Mon Apr 15 15:30:53 2013 +0200 +++ b/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Thu Apr 25 16:17:48 2013 +0200 @@ -460,6 +460,11 @@ } throw new IOException("Can't find " + resource); } + + @Override + public String getModule(String resource) throws IOException { + return null; + } } private static class Page extends HttpHandler { diff -r c2386b2f53d0 -r a6bacea2518f rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java Mon Apr 15 15:30:53 2013 +0200 +++ b/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java Thu Apr 25 16:17:48 2013 +0200 @@ -128,5 +128,10 @@ } throw new IOException("Can't find " + resource); } + + @Override + public String getModule(String resource) throws IOException { + return null; + } } } diff -r c2386b2f53d0 -r a6bacea2518f rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Mon Apr 15 15:30:53 2013 +0200 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Thu Apr 25 16:17:48 2013 +0200 @@ -193,5 +193,7 @@ * or the file cannot be found */ public InputStream get(String resource) throws IOException; + + public String getModule(String resource) throws IOException; } } diff -r c2386b2f53d0 -r a6bacea2518f rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Mon Apr 15 15:30:53 2013 +0200 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Thu Apr 25 16:17:48 2013 +0200 @@ -30,10 +30,6 @@ final Appendable out; final ObfuscationDelegate obfuscationDelegate; - protected ByteCodeToJavaScript(Appendable out) { - this(out, ObfuscationDelegate.NULL); - } - protected ByteCodeToJavaScript( Appendable out, ObfuscationDelegate obfuscationDelegate) { this.out = out; @@ -66,7 +62,7 @@ return classOperation; } - abstract String getVMObject(); + abstract String getExportsObject(); /** Prints out a debug message. * @@ -243,7 +239,7 @@ out.append("\n return arguments[0] ? new CLS() : CLS.prototype;"); out.append("\n};"); - obfuscationDelegate.exportClass(out, getVMObject(), className, jc); + obfuscationDelegate.exportClass(out, getExportsObject(), className, jc); // StringBuilder sb = new StringBuilder(); // for (String init : toInitilize.toArray()) { diff -r c2386b2f53d0 -r a6bacea2518f rt/vm/src/main/java/org/apidesign/vm4brwsr/LdrRsrcs.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/LdrRsrcs.java Mon Apr 15 15:30:53 2013 +0200 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/LdrRsrcs.java Thu Apr 25 16:17:48 2013 +0200 @@ -35,6 +35,43 @@ @Override public InputStream get(String name) throws IOException { + return findSource(name).openStream(); + } + + @Override + public String getModule(String name) throws IOException { + final URL url = findSource(name); + + if (!"jar".equalsIgnoreCase(url.getProtocol())) { + return null; + } + + final String fullPathString = url.getPath(); + final int sepIndex = fullPathString.indexOf('!'); + final String jarPathString = + (sepIndex != -1) ? fullPathString.substring(0, sepIndex) + : fullPathString; + if (!jarPathString.endsWith(".jar")) { + return null; + } + + String moduleName = + jarPathString.substring( + jarPathString.lastIndexOf('/') + 1, + jarPathString.length() - 4); + if (moduleName.endsWith("-SNAPSHOT")) { + moduleName = moduleName.substring( + 0, moduleName.length() - 9); + } + final int dashIndex = moduleName.lastIndexOf('-'); + if (dashIndex != -1) { + moduleName = moduleName.substring(0, dashIndex); + } + + return moduleName; + } + + private URL findSource(String name) throws IOException { Enumeration en = loader.getResources(name); URL u = null; while (en.hasMoreElements()) { @@ -43,6 +80,6 @@ if (u == null) { throw new IOException("Can't find " + name); } - return u.openStream(); + return u; } } diff -r c2386b2f53d0 -r a6bacea2518f rt/vm/src/main/java/org/apidesign/vm4brwsr/Main.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/Main.java Mon Apr 15 15:30:53 2013 +0200 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/Main.java Thu Apr 25 16:17:48 2013 +0200 @@ -18,9 +18,16 @@ package org.apidesign.vm4brwsr; import java.io.BufferedWriter; +import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.Writer; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; /** Generator of JavaScript from bytecode of classes on classpath of the VM * with a Main method. @@ -30,7 +37,7 @@ final class Main { private Main() {} - public static void main(String... args) throws IOException { + public static void main(String... args) throws IOException, URISyntaxException { final String obfuscate = "--obfuscatelevel"; if (args.length < 2) { @@ -50,7 +57,9 @@ System.err.println("] java/lang/Class org/your/App ..."); System.exit(9); } - + + final ClassLoader mainClassLoader = Main.class.getClassLoader(); + ObfuscationLevel obfLevel = ObfuscationLevel.NONE; StringArray classes = new StringArray(); String generateTo = null; @@ -78,15 +87,114 @@ if (generateTo == null) { generateTo = args[i]; } else { - classes = classes.addAndNew(args[i]); + collectClasses(classes, mainClassLoader, args[i]); } } try (Writer w = new BufferedWriter(new FileWriter(generateTo))) { Bck2Brwsr.newCompiler(). obfuscation(obfLevel). addRootClasses(classes.toArray()). - resources(Main.class.getClassLoader()). + resources(mainClassLoader). generate(w); } } + + private static void collectClasses( + final StringArray dest, + final ClassLoader cl, final String relativePath) + throws IOException, URISyntaxException { + final Enumeration urls = cl.getResources(relativePath); + if (!urls.hasMoreElements()) { + dest.add(relativePath); + return; + } + do { + final URL url = urls.nextElement(); + switch (url.getProtocol()) { + case "file": + collectClasses(dest, relativePath, + new File(new URI(url.toString()))); + continue; + case "jar": + final String fullPath = url.getPath(); + final int sepIndex = fullPath.indexOf('!'); + final String jarFilePath = + (sepIndex != -1) ? fullPath.substring(0, sepIndex) + : fullPath; + + final URI jarUri = new URI(jarFilePath); + if (jarUri.getScheme().equals("file")) { + try (JarFile jarFile = new JarFile(new File(jarUri))) { + collectClasses(dest, relativePath, jarFile); + continue; + } + } + break; + } + + dest.add(relativePath); + } while (urls.hasMoreElements()); + } + + private static void collectClasses(final StringArray dest, + final String relativePath, + final File file) { + if (file.isDirectory()) { + final File[] subFiles = file.listFiles(); + for (final File subFile: subFiles) { + collectClasses(dest, + extendPath(relativePath, subFile.getName()), + subFile); + } + + return; + } + + final String filePath = file.getPath(); + if (filePath.endsWith(".class")) { + validateAndAddClass(dest, relativePath); + } + } + + private static void collectClasses(final StringArray dest, + final String relativePath, + final JarFile jarFile) { + if (relativePath.endsWith(".class")) { + if (jarFile.getJarEntry(relativePath) != null) { + validateAndAddClass(dest, relativePath); + } + + return; + } + + final String expectedPrefix = + relativePath.endsWith("/") ? relativePath + : relativePath + '/'; + final Enumeration entries = jarFile.entries(); + while (entries.hasMoreElements()) { + final JarEntry entry = entries.nextElement(); + if (!entry.isDirectory()) { + final String entryName = entry.getName(); + if (entryName.startsWith(expectedPrefix) + && entryName.endsWith(".class")) { + validateAndAddClass(dest, entryName); + } + } + } + } + + private static String extendPath(final String relativePath, + final String fileName) { + return relativePath.endsWith("/") ? relativePath + fileName + : relativePath + '/' + fileName; + } + + private static void validateAndAddClass(final StringArray dest, + final String relativePath) { + final String className = + relativePath.substring(0, relativePath.length() - 6); + if (!className.endsWith("package-info")) { + dest.add(className); + } + } } diff -r c2386b2f53d0 -r a6bacea2518f rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Mon Apr 15 15:30:53 2013 +0200 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Thu Apr 25 16:17:48 2013 +0200 @@ -24,11 +24,7 @@ * * @author Jaroslav Tulach */ -class VM extends ByteCodeToJavaScript { - public VM(Appendable out) { - super(out); - } - +abstract class VM extends ByteCodeToJavaScript { private VM(Appendable out, ObfuscationDelegate obfuscationDelegate) { super(out, obfuscationDelegate); } @@ -49,16 +45,27 @@ } static void compile(Bck2Brwsr.Resources l, Appendable out, StringArray names) throws IOException { - new VM(out).doCompile(l, names); + VM vm = new Standalone(out, ObfuscationDelegate.NULL); + vm.doCompile(l, names); } static void compile(Bck2Brwsr.Resources l, Appendable out, StringArray names, ObfuscationDelegate obfuscationDelegate) throws IOException { - new VM(out, obfuscationDelegate).doCompile(l, names); + VM vm = new Standalone(out, obfuscationDelegate); + vm.doCompile(l, names); } - protected void doCompile(Bck2Brwsr.Resources l, StringArray names) throws IOException { - out.append("(function VM(global) {var fillInVMSkeleton = function(vm) {"); + private void doCompile(Bck2Brwsr.Resources l, StringArray names) throws IOException { + generatePrologue(); + generateBody(l, names); + generateEpilogue(); + } + + protected abstract void generatePrologue() throws IOException; + + protected abstract void generateEpilogue() throws IOException; + + protected void generateBody(Bck2Brwsr.Resources l, StringArray names) throws IOException { StringArray processed = new StringArray(); StringArray initCode = new StringArray(); for (String baseClass : names.toArray()) { @@ -76,7 +83,7 @@ } InputStream is = loadClass(l, name); if (is == null) { - throw new IOException("Can't find class " + name); + throw new IOException("Can't find class " + name); } try { String ic = compile(is); @@ -91,11 +98,11 @@ break; } } - throw new IOException("Error while compiling " + name + "\n" + throw new IOException("Error while compiling " + name + "\n" + seq.subSequence(lastBlock + 1, seq.length()), ex ); } else { - throw new IOException("Error while compiling " + name + "\n" + throw new IOException("Error while compiling " + name + "\n" + out, ex ); } @@ -113,7 +120,7 @@ readResource(emul, out); } scripts = new StringArray(); - + StringArray toInit = StringArray.asList(references.toArray()); toInit.reverse(); @@ -128,36 +135,8 @@ } } } - out.append( - " return vm;\n" - + " };\n" - + " global.bck2brwsr = function() {\n" - + " var args = Array.prototype.slice.apply(arguments);\n" - + " var vm = fillInVMSkeleton({});\n" - + " var loader = {};\n" - + " loader.vm = vm;\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" - + " 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 (vm.loadClass) {\n" - + " throw 'Cannot initialize the bck2brwsr VM twice!';\n" - + " }\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));"); } + private static void readResource(InputStream emul, Appendable out) throws IOException { try { int state = 0; @@ -241,8 +220,80 @@ return "vm." + className; } - @Override - String getVMObject() { - return "vm"; + private static final class Standalone extends VM { + private Standalone(Appendable out, + ObfuscationDelegate obfuscationDelegate) { + super(out, obfuscationDelegate); + } + + @Override + protected void generatePrologue() throws IOException { + out.append("(function VM(global) {var fillInVMSkeleton = function(vm) {"); + } + + @Override + protected void generateEpilogue() throws IOException { + out.append( + " return vm;\n" + + " };\n" + + " global.bck2brwsr = function() {\n" + + " var args = Array.prototype.slice.apply(arguments);\n" + + " var vm = fillInVMSkeleton({});\n" + + " var loader = {};\n" + + " loader.vm = vm;\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" + + " 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 (vm.loadClass) {\n" + + " throw 'Cannot initialize the bck2brwsr VM twice!';\n" + + " }\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));"); + } + + @Override + String getExportsObject() { + return "vm"; + } + } + + private static final class Extension extends VM { + private final String name; + + private Extension(String name, + Appendable out, + ObfuscationDelegate obfuscationDelegate) { + super(out, obfuscationDelegate); + this.name = name; + } + + @Override + protected void generatePrologue() throws IOException { + out.append("bck2brwsr.registerExtension(function(exports) {\n" + + " var vm = {};\n"); + } + + @Override + protected void generateEpilogue() throws IOException { + out.append("});"); + } + + @Override + String getExportsObject() { + return "exports"; + } } } diff -r c2386b2f53d0 -r a6bacea2518f rt/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java Mon Apr 15 15:30:53 2013 +0200 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java Thu Apr 25 16:17:48 2013 +0200 @@ -106,7 +106,7 @@ private final VMLazy lazy; public Gen(VMLazy vm, Appendable out) { - super(out); + super(out, ObfuscationDelegate.NULL); this.lazy = vm; } @@ -153,7 +153,7 @@ } @Override - String getVMObject() { + String getExportsObject() { return "vm"; } } diff -r c2386b2f53d0 -r a6bacea2518f rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java Mon Apr 15 15:30:53 2013 +0200 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java Thu Apr 25 16:17:48 2013 +0200 @@ -166,5 +166,10 @@ } return u.openStream(); } + + @Override + public String getModule(String resource) throws IOException { + return null; + } } } diff -r c2386b2f53d0 -r a6bacea2518f rt/vm/src/test/java/org/apidesign/vm4brwsr/VMinVM.java --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/VMinVM.java Mon Apr 15 15:30:53 2013 +0200 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/VMinVM.java Thu Apr 25 16:17:48 2013 +0200 @@ -45,7 +45,7 @@ } @Override - String getVMObject() { + String getExportsObject() { return "global"; } }