# HG changeset patch # User Jaroslav Tulach # Date 1401119576 -7200 # Node ID 36746c46716a147172ba1f14dfb3a46843ae0279 # Parent ec62383beb7d0470424c7c73ad511fa7eb140353 Moving the JAR file parsing and processing into a shared library diff -r ec62383beb7d -r 36746c46716a launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/BaseHTTPLauncher.java --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/BaseHTTPLauncher.java Mon May 26 16:20:51 2014 +0200 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/BaseHTTPLauncher.java Mon May 26 17:52:56 2014 +0200 @@ -562,7 +562,7 @@ abstract void generateBck2BrwsrJS(StringBuilder sb, Res loader) throws IOException; abstract String harnessResource(); - String compileJar(JarFile jar) throws IOException { + String compileJar(URL jar) throws IOException { return null; } String compileFromClassPath(URL f, Res loader) throws IOException { @@ -582,8 +582,8 @@ final class Res { private final Set ignore = new HashSet(); - String compileJar(JarFile jar, URL jarURL) throws IOException { - String ret = BaseHTTPLauncher.this.compileJar(jar); + String compileJar(URL jarURL) throws IOException { + String ret = BaseHTTPLauncher.this.compileJar(jarURL); ignore.add(jarURL); return ret; } @@ -745,7 +745,7 @@ response.setCharacterEncoding("UTF-8"); if (url.getProtocol().equals("jar")) { JarURLConnection juc = (JarURLConnection) url.openConnection(); - String s = loader.compileJar(juc.getJarFile(), juc.getJarFileURL()); + String s = loader.compileJar(juc.getJarFileURL()); if (s != null) { Writer w = response.getWriter(); w.append(s); diff -r ec62383beb7d -r 36746c46716a launcher/http/pom.xml --- a/launcher/http/pom.xml Mon May 26 16:20:51 2014 +0200 +++ b/launcher/http/pom.xml Mon May 26 17:52:56 2014 +0200 @@ -67,5 +67,11 @@ ${project.version} test + + org.apidesign.bck2brwsr + aot + 0.9-SNAPSHOT + jar + diff -r ec62383beb7d -r 36746c46716a launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java --- a/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Mon May 26 16:20:51 2014 +0200 +++ b/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Mon May 26 17:52:56 2014 +0200 @@ -18,16 +18,14 @@ package org.apidesign.bck2brwsr.launcher; import java.io.File; -import java.io.FileReader; import java.io.IOException; -import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.net.MalformedURLException; +import java.net.URISyntaxException; import java.net.URL; import java.util.HashSet; import java.util.Set; -import java.util.jar.JarFile; import java.util.logging.Level; /** @@ -48,8 +46,14 @@ } @Override - String compileJar(JarFile jar) throws IOException { - return CompileCP.compileJAR(jar, testClasses); + String compileJar(URL jar) throws IOException { + File f; + try { + f = new File(jar.toURI()); + } catch (URISyntaxException ex) { + throw new IOException(ex); + } + return CompileCP.compileJAR(f, testClasses); } @Override diff -r ec62383beb7d -r 36746c46716a launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/CompileCP.java --- a/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/CompileCP.java Mon May 26 16:20:51 2014 +0200 +++ b/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/CompileCP.java Mon May 26 17:52:56 2014 +0200 @@ -17,28 +17,22 @@ */ package org.apidesign.bck2brwsr.launcher; -import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.io.StringWriter; import java.net.JarURLConnection; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; -import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.zip.ZipEntry; +import org.apidesign.bck2brwsr.aot.Bck2BrwsrJars; import org.apidesign.bck2brwsr.launcher.BaseHTTPLauncher.Res; import org.apidesign.vm4brwsr.Bck2Brwsr; -import org.apidesign.vm4brwsr.ObfuscationLevel; /** * @@ -46,31 +40,11 @@ */ class CompileCP { private static final Logger LOG = Logger.getLogger(CompileCP.class.getName()); - static String compileJAR(final JarFile jar, Set testClasses) + static String compileJAR(final File jar, Set testClasses) throws IOException { - List arr = new ArrayList<>(); - List classes = new ArrayList<>(); - Set keep = new HashSet(testClasses); - listJAR(jar, classes, arr, keep); - StringWriter w = new StringWriter(); try { - class JarRes extends EmulationResources implements Bck2Brwsr.Resources { - @Override - public InputStream get(String resource) throws IOException { - InputStream is = jar.getInputStream(new ZipEntry(resource)); - return is == null ? super.get(resource) : is; - } - } - - Bck2Brwsr.newCompiler() - .addClasses(classes.toArray(new String[0])) - .addExported(keep.toArray(new String[0])) - .addResources(arr.toArray(new String[0])) - //.obfuscation(ObfuscationLevel.FULL) - .library(true) - .resources(new JarRes()) - .generate(w); + Bck2BrwsrJars.configureFrom(null, jar).generate(w); w.flush(); return w.toString(); } catch (IOException ex) { @@ -126,56 +100,7 @@ return null; } - private static void listJAR( - JarFile j, List classes, - List resources, Set keep - ) throws IOException { - Enumeration en = j.entries(); - while (en.hasMoreElements()) { - JarEntry e = en.nextElement(); - final String n = e.getName(); - if (n.endsWith("/")) { - continue; - } - int last = n.lastIndexOf('/'); - String pkg = n.substring(0, last + 1); - if (skipPkg(pkg)) { - continue; - } - if (n.endsWith(".class")) { - classes.add(n.substring(0, n.length() - 6)); - } else { - resources.add(n); - if (n.startsWith("META-INF/services/") && keep != null) { - BufferedReader r = new BufferedReader(new InputStreamReader(j.getInputStream(e))); - for (;;) { - String l = r.readLine(); - if (l == null) { - break; - } - if (l.startsWith("#")) { - continue; - } - keep.add(l.replace('.', '/')); - } - } - } - } - String exp = j.getManifest().getMainAttributes().getValue("Export-Package"); - if (exp != null && keep != null) { - for (String def : exp.split(",")) { - for (String sep : def.split(";")) { - keep.add(sep.replace('.', '/') + "/"); - break; - } - } - } - } - private static boolean skipPkg(String pkg) { - return pkg.equals("org/apidesign/bck2brwsr/launcher/"); - } - private static void listDir(File f, String pref, List classes, List resources) throws IOException { File[] arr = f.listFiles(); if (arr == null) { @@ -193,21 +118,24 @@ } static void compileVM(StringBuilder sb, final Res r) throws IOException { - List arr = new ArrayList<>(); - List classes = new ArrayList<>(); - - { + final Bck2Brwsr rt; + try { URL u = r.get(InterruptedException.class.getName().replace('.', '/') + ".class", 0); JarURLConnection juc = (JarURLConnection)u.openConnection(); - listJAR(juc.getJarFile(), classes, arr, null); + rt = Bck2BrwsrJars.configureFrom(null, new File(juc.getJarFileURL().toURI())); + } catch (URISyntaxException ex) { + throw new IOException(ex); } - { + final Bck2Brwsr all; + try { URL u = r.get(Bck2Brwsr.class.getName().replace('.', '/') + ".class", 0); JarURLConnection juc = (JarURLConnection)u.openConnection(); - listJAR(juc.getJarFile(), classes, arr, null); + all = Bck2BrwsrJars.configureFrom(rt, new File(juc.getJarFileURL().toURI())); + } catch (URISyntaxException ex) { + throw new IOException(ex); } - Bck2Brwsr.newCompiler().addRootClasses(classes.toArray(new String[0])) + all.library(false) //.obfuscation(ObfuscationLevel.FULL) .resources(new Bck2Brwsr.Resources() { @Override @@ -222,7 +150,7 @@ @Override public InputStream get(String name) throws IOException { - Enumeration en = CompileCP.class.getClassLoader().getResources(name); + Enumeration en = Bck2BrwsrJars.class.getClassLoader().getResources(name); URL u = null; while (en.hasMoreElements()) { u = en.nextElement(); @@ -232,10 +160,11 @@ return null; } if (u.toExternalForm().contains("/rt.jar!")) { - LOG.warning(name + "No bootdelegation for "); + LOG.log(Level.WARNING, "{0}No bootdelegation for ", name); return null; } return u.openStream(); } } + } diff -r ec62383beb7d -r 36746c46716a rt/aot/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/aot/pom.xml Mon May 26 17:52:56 2014 +0200 @@ -0,0 +1,20 @@ + + + 4.0.0 + + org.apidesign.bck2brwsr + rt + 0.9-SNAPSHOT + + Ahead of Time Compilation + aot + jar + + + org.apidesign.bck2brwsr + vm4brwsr + ${project.version} + jar + + + \ No newline at end of file diff -r ec62383beb7d -r 36746c46716a rt/aot/src/main/java/org/apidesign/bck2brwsr/aot/Bck2BrwsrJars.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/aot/src/main/java/org/apidesign/bck2brwsr/aot/Bck2BrwsrJars.java Mon May 26 17:52:56 2014 +0200 @@ -0,0 +1,157 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.bck2brwsr.aot; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.zip.ZipEntry; +import org.apidesign.vm4brwsr.Bck2Brwsr; + +/** Utilities to process JAR files and set a compiler + * up + * + * @author Jaroslav Tulach + */ +public final class Bck2BrwsrJars { + private static final Logger LOG = Logger.getLogger(Bck2BrwsrJars.class.getName()); + + private Bck2BrwsrJars() { + } + + /** Creates new compiler pre-configured from the content of + * provided JAR file. The compiler will compile all classes. + * The system understands OSGi manifest entries and will export + * all packages that are exported in the JAR file. The system + * also recognizes META-INF/services and makes sure the file names + * are not mangled. + * + * @param c the compiler to {@link Bck2Brwsr#addClasses(java.lang.String...) add classes}, + * {@link Bck2Brwsr#addResources(java.lang.String...) add resources} and + * {@link Bck2Brwsr#addExported(java.lang.String...) exported objects} to. + * Can be null - in such case an + * {@link Bck2Brwsr#newCompiler() empty compiler} is constructed. + * @param jar the file to process + * @return newly configured compiler + * @throws IOException if something goes wrong + */ + public static Bck2Brwsr configureFrom(Bck2Brwsr c, File jar) throws IOException { + try (JarFile jf = new JarFile(jar)) { + List classes = new ArrayList<>(); + List resources = new ArrayList<>(); + Set exported = new HashSet<>(); + + listJAR(jf, classes, resources, exported); + + class JarRes extends EmulationResources implements Bck2Brwsr.Resources { + + @Override + public InputStream get(String resource) throws IOException { + InputStream is = jf.getInputStream(new ZipEntry(resource)); + return is == null ? super.get(resource) : is; + } + } + return Bck2Brwsr.newCompiler() + .library(true) + .addClasses(classes.toArray(new String[classes.size()])) + .addExported(exported.toArray(new String[exported.size()])) + .addResources(resources.toArray(new String[resources.size()])) + .resources(new JarRes()); + } + } + + private static void listJAR( + JarFile j, List classes, + List resources, Set keep + ) throws IOException { + Enumeration en = j.entries(); + while (en.hasMoreElements()) { + JarEntry e = en.nextElement(); + final String n = e.getName(); + if (n.endsWith("/")) { + continue; + } + int last = n.lastIndexOf('/'); + String pkg = n.substring(0, last + 1); + if (pkg.startsWith("java/")) { + keep.add(pkg); + } + if (n.endsWith(".class")) { + classes.add(n.substring(0, n.length() - 6)); + } else { + resources.add(n); + if (n.startsWith("META-INF/services/") && keep != null) { + BufferedReader r = new BufferedReader(new InputStreamReader(j.getInputStream(e))); + for (;;) { + String l = r.readLine(); + if (l == null) { + break; + } + if (l.startsWith("#")) { + continue; + } + keep.add(l.replace('.', '/')); + } + } + } + } + String exp = j.getManifest().getMainAttributes().getValue("Export-Package"); + if (exp != null && keep != null) { + for (String def : exp.split(",")) { + for (String sep : def.split(";")) { + keep.add(sep.replace('.', '/') + "/"); + break; + } + } + } + } + + static class EmulationResources implements Bck2Brwsr.Resources { + + @Override + public InputStream get(String name) throws IOException { + Enumeration en = Bck2BrwsrJars.class.getClassLoader().getResources(name); + URL u = null; + while (en.hasMoreElements()) { + u = en.nextElement(); + } + if (u == null) { + LOG.log(Level.WARNING, "Cannot find {0}", name); + return null; + } + if (u.toExternalForm().contains("/rt.jar!")) { + LOG.log(Level.WARNING, "{0}No bootdelegation for ", name); + return null; + } + return u.openStream(); + } + } + +} diff -r ec62383beb7d -r 36746c46716a rt/mojo/pom.xml --- a/rt/mojo/pom.xml Mon May 26 16:20:51 2014 +0200 +++ b/rt/mojo/pom.xml Mon May 26 17:52:56 2014 +0200 @@ -91,5 +91,11 @@ launcher.fx ${project.version} + + org.apidesign.bck2brwsr + aot + 0.9-SNAPSHOT + jar + diff -r ec62383beb7d -r 36746c46716a rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/AheadOfTime.java --- a/rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/AheadOfTime.java Mon May 26 16:20:51 2014 +0200 +++ b/rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/AheadOfTime.java Mon May 26 17:52:56 2014 +0200 @@ -46,6 +46,7 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.project.MavenProject; +import org.apidesign.bck2brwsr.aot.Bck2BrwsrJars; import org.apidesign.vm4brwsr.Bck2Brwsr; import org.apidesign.vm4brwsr.ObfuscationLevel; @@ -130,22 +131,12 @@ } private void aotLibrary(Artifact a, File js, URLClassLoader loader) throws IOException { - List classes = new ArrayList(); - List resources = new ArrayList(); - Set exported = new HashSet(); - - JarFile jf = new JarFile(a.getFile()); - listJAR(jf, classes , resources, exported); - FileWriter w = new FileWriter(js); - Bck2Brwsr.newCompiler(). - obfuscation(obfuscation). - library(true). - resources(loader). - addResources(resources.toArray(new String[0])). - addClasses(classes.toArray(new String[0])). - addExported(exported.toArray(new String[0])). - generate(w); + Bck2Brwsr c = Bck2BrwsrJars.configureFrom(null, a.getFile()); + c. + obfuscation(obfuscation). + resources(loader). + generate(w); w.close(); } private static URLClassLoader buildClassLoader(File root, Collection deps) throws MalformedURLException { @@ -160,54 +151,4 @@ } return new URLClassLoader(arr.toArray(new URL[0]), Java2JavaScript.class.getClassLoader()); } - - private static void listJAR( - JarFile j, List classes, - List resources, Set exported - ) throws IOException { - Enumeration en = j.entries(); - while (en.hasMoreElements()) { - JarEntry e = en.nextElement(); - final String n = e.getName(); - if (n.endsWith("/")) { - continue; - } - int last = n.lastIndexOf('/'); - String pkg = n.substring(0, last + 1); - if (n.endsWith(".class")) { - classes.add(n.substring(0, n.length() - 6)); - } else { - resources.add(n); - if (n.startsWith("META-INF/services/") && exported != null) { - final InputStream is = j.getInputStream(e); - exportedServices(is, exported); - is.close(); - } - } - } - String exp = j.getManifest().getMainAttributes().getValue("Export-Package"); - if (exp != null && exported != null) { - for (String def : exp.split(",")) { - for (String sep : def.split(";")) { - exported.add(sep.replace('.', '/') + "/"); - break; - } - } - } - } - - static void exportedServices(final InputStream is, Set exported) throws IOException { - BufferedReader r = new BufferedReader(new InputStreamReader(is)); - for (;;) { - String l = r.readLine(); - if (l == null) { - break; - } - if (l.startsWith("#")) { - continue; - } - exported.add(l.replace('.', '/')); - } - } - } diff -r ec62383beb7d -r 36746c46716a rt/pom.xml --- a/rt/pom.xml Mon May 26 16:20:51 2014 +0200 +++ b/rt/pom.xml Mon May 26 17:52:56 2014 +0200 @@ -17,5 +17,6 @@ mojo vm vmtest + aot