Export only test classes, classes from exported packages and those referenced in META-INF/services closure
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 05 May 2014 10:16:30 +0200
branchclosure
changeset 1525777bd3ed81ba
parent 1524 ed9f8f93960f
child 1526 4d8e295a2c2e
Export only test classes, classes from exported packages and those referenced in META-INF/services
launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java
launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/CompileCP.java
rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java
     1.1 --- a/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java	Mon May 05 08:42:33 2014 +0200
     1.2 +++ b/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java	Mon May 05 10:16:30 2014 +0200
     1.3 @@ -25,9 +25,10 @@
     1.4  import java.io.Reader;
     1.5  import java.net.MalformedURLException;
     1.6  import java.net.URL;
     1.7 +import java.util.HashSet;
     1.8 +import java.util.Set;
     1.9  import java.util.jar.JarFile;
    1.10  import java.util.logging.Level;
    1.11 -import org.apidesign.vm4brwsr.Bck2Brwsr;
    1.12  
    1.13  /**
    1.14   * Lightweight server to launch Bck2Brwsr applications and tests.
    1.15 @@ -35,6 +36,7 @@
    1.16   * execution engine.
    1.17   */
    1.18  final class Bck2BrwsrLauncher extends BaseHTTPLauncher {
    1.19 +    private Set<String> testClasses = new HashSet<String>();
    1.20      
    1.21      public Bck2BrwsrLauncher(String cmd) {
    1.22          super(cmd);
    1.23 @@ -47,7 +49,13 @@
    1.24  
    1.25      @Override
    1.26      String compileJar(JarFile jar) throws IOException {
    1.27 -        return CompileCP.compileJAR(jar);
    1.28 +        return CompileCP.compileJAR(jar, testClasses);
    1.29 +    }
    1.30 +
    1.31 +    @Override
    1.32 +    public InvocationContext createInvocation(Class<?> clazz, String method) {
    1.33 +        testClasses.add(clazz.getName().replace('.', '/'));
    1.34 +        return super.createInvocation(clazz, method);
    1.35      }
    1.36  
    1.37      @Override String compileFromClassPath(URL f, Res loader) throws IOException {
     2.1 --- a/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/CompileCP.java	Mon May 05 08:42:33 2014 +0200
     2.2 +++ b/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/CompileCP.java	Mon May 05 10:16:30 2014 +0200
     2.3 @@ -17,16 +17,20 @@
     2.4   */
     2.5  package org.apidesign.bck2brwsr.launcher;
     2.6  
     2.7 +import java.io.BufferedReader;
     2.8  import java.io.File;
     2.9  import java.io.IOException;
    2.10  import java.io.InputStream;
    2.11 +import java.io.InputStreamReader;
    2.12  import java.io.StringWriter;
    2.13  import java.net.JarURLConnection;
    2.14  import java.net.URISyntaxException;
    2.15  import java.net.URL;
    2.16  import java.util.ArrayList;
    2.17  import java.util.Enumeration;
    2.18 +import java.util.HashSet;
    2.19  import java.util.List;
    2.20 +import java.util.Set;
    2.21  import java.util.jar.JarEntry;
    2.22  import java.util.jar.JarFile;
    2.23  import java.util.logging.Level;
    2.24 @@ -41,10 +45,26 @@
    2.25   */
    2.26  class CompileCP {
    2.27      private static final Logger LOG = Logger.getLogger(CompileCP.class.getName());
    2.28 -    static String compileJAR(final JarFile jar) throws IOException {
    2.29 +    static String compileJAR(final JarFile jar, Set<String> testClasses) 
    2.30 +    throws IOException {
    2.31          List<String> arr = new ArrayList<>();
    2.32          List<String> classes = new ArrayList<>();
    2.33 -        listJAR(jar, classes, arr);
    2.34 +        Set<String> exported = new HashSet<String>();
    2.35 +        Set<String> keep = new HashSet<String>(testClasses);
    2.36 +        listJAR(jar, classes, arr, exported, keep);
    2.37 +        List<String> root = new ArrayList<>();
    2.38 +        for (String c : classes) {
    2.39 +            if (keep.contains(c)) {
    2.40 +                root.add(c);
    2.41 +                continue;
    2.42 +            }
    2.43 +            int slash = c.lastIndexOf('/');
    2.44 +            String pkg = c.substring(0, slash + 1);
    2.45 +            if (exported.contains(pkg)) {
    2.46 +                root.add(c);
    2.47 +            }
    2.48 +        }
    2.49 +        
    2.50          StringWriter w = new StringWriter();
    2.51          try {
    2.52              class JarRes extends EmulationResources implements Bck2Brwsr.Resources {
    2.53 @@ -57,6 +77,7 @@
    2.54              
    2.55              Bck2Brwsr.newCompiler()
    2.56                  .addClasses(classes.toArray(new String[0]))
    2.57 +                .addRootClasses(root.toArray(new String[0]))
    2.58                  .addResources(arr.toArray(new String[0]))
    2.59                  .library(true)
    2.60                  .resources(new JarRes())
    2.61 @@ -115,7 +136,10 @@
    2.62          return null;
    2.63      }
    2.64      
    2.65 -    private static void listJAR(JarFile j, List<String> classes, List<String> resources) throws IOException {
    2.66 +    private static void listJAR(
    2.67 +        JarFile j, List<String> classes,
    2.68 +        List<String> resources, Set<String> exported, Set<String> keep
    2.69 +    ) throws IOException {
    2.70          Enumeration<JarEntry> en = j.entries();
    2.71          while (en.hasMoreElements()) {
    2.72              JarEntry e = en.nextElement();
    2.73 @@ -135,6 +159,28 @@
    2.74                  classes.add(n.substring(0, n.length() - 6));
    2.75              } else {
    2.76                  resources.add(n);
    2.77 +                if (n.startsWith("META-INF/services/") && keep != null) {
    2.78 +                    BufferedReader r = new BufferedReader(new InputStreamReader(j.getInputStream(e)));
    2.79 +                    for (;;) {
    2.80 +                        String l = r.readLine();
    2.81 +                        if (l == null) {
    2.82 +                            break;
    2.83 +                        }
    2.84 +                        if (l.startsWith("#")) {
    2.85 +                            continue;
    2.86 +                        }
    2.87 +                        keep.add(l.replace('.', '/'));
    2.88 +                    }
    2.89 +                }
    2.90 +            }
    2.91 +        }
    2.92 +        String exp = j.getManifest().getMainAttributes().getValue("Export-Package");
    2.93 +        if (exp != null && exported != null) {
    2.94 +            for (String def : exp.split(",")) {
    2.95 +                for (String sep : def.split(";")) {
    2.96 +                    exported.add(sep.replace('.', '/') + "/");
    2.97 +                    break;
    2.98 +                }
    2.99              }
   2.100          }
   2.101      }
   2.102 @@ -168,7 +214,7 @@
   2.103          
   2.104          List<String> arr = new ArrayList<>();
   2.105          List<String> classes = new ArrayList<>();
   2.106 -        listJAR(juc.getJarFile(), classes, arr);
   2.107 +        listJAR(juc.getJarFile(), classes, arr, null, null);
   2.108  
   2.109          Bck2Brwsr.newCompiler().addRootClasses(classes.toArray(new String[0]))
   2.110              .resources(new Bck2Brwsr.Resources() {
     3.1 --- a/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java	Mon May 05 08:42:33 2014 +0200
     3.2 +++ b/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java	Mon May 05 10:16:30 2014 +0200
     3.3 @@ -43,6 +43,7 @@
     3.4      private final boolean fail;
     3.5      private final HtmlFragment html;
     3.6      private final Http.Resource[] http;
     3.7 +    private final InvocationContext c;
     3.8      Object value;
     3.9  
    3.10      Bck2BrwsrCase(Method m, String type, Launcher l, boolean fail, HtmlFragment html, Http.Resource[] http) {
    3.11 @@ -52,12 +53,12 @@
    3.12          this.fail = fail;
    3.13          this.html = html;
    3.14          this.http = http;
    3.15 +        this.c = l != null ? l.createInvocation(m.getDeclaringClass(), m.getName()) : null;
    3.16      }
    3.17  
    3.18      @Test(groups = "run")
    3.19      public void executeCode() throws Throwable {
    3.20          if (l != null) {
    3.21 -            InvocationContext c = l.createInvocation(m.getDeclaringClass(), m.getName());
    3.22              if (html != null) {
    3.23                  c.setHtmlFragment(html.value());
    3.24              }