#251105: Move all asm related functionality to FnUtils and reference it only via reflection to make transitive closure of necessary API classes smaller.
authorJaroslav Tulach <jtulach@netbeans.org>
Tue, 31 Mar 2015 15:40:22 +0200
changeset 932f2de2ae88589
parent 931 41076da07b68
child 933 9d158eb4a797
#251105: Move all asm related functionality to FnUtils and reference it only via reflection to make transitive closure of necessary API classes smaller.
Task #251105 - Elminite warnings about missing Asm classes
boot/src/main/java/net/java/html/boot/BrowserBuilder.java
boot/src/main/java/org/netbeans/html/boot/impl/FnContext.java
boot/src/main/java/org/netbeans/html/boot/impl/FnUtils.java
boot/src/main/java/org/netbeans/html/boot/impl/JsClassLoader.java
boot/src/test/java/org/netbeans/html/boot/impl/JsClassLoaderTest.java
     1.1 --- a/boot/src/main/java/net/java/html/boot/BrowserBuilder.java	Tue Mar 10 15:22:39 2015 +0100
     1.2 +++ b/boot/src/main/java/net/java/html/boot/BrowserBuilder.java	Tue Mar 31 15:40:22 2015 +0200
     1.3 @@ -68,7 +68,6 @@
     1.4  import org.netbeans.html.context.spi.Contexts.Id;
     1.5  import org.netbeans.html.boot.impl.FindResources;
     1.6  import org.netbeans.html.boot.impl.FnContext;
     1.7 -import org.netbeans.html.boot.impl.FnUtils;
     1.8  
     1.9  /** Use this builder to launch your Java/HTML based application. Typical
    1.10   * usage in a main method of your application looks like this: 
    1.11 @@ -295,11 +294,11 @@
    1.12              if (res == null) {
    1.13                  activeLoader = myCls.getClassLoader();
    1.14              } else {
    1.15 -                if (!FnContext.isAsmPresent(res)) {
    1.16 +                FImpl impl = new FImpl(myCls.getClassLoader());
    1.17 +                activeLoader = FnContext.newLoader(res, impl, dfnr, myCls.getClassLoader().getParent());
    1.18 +                if (activeLoader == null) {
    1.19                      throw new IllegalStateException("Cannot find asm-5.0.jar classes!");
    1.20                  }
    1.21 -                FImpl impl = new FImpl(myCls.getClassLoader());
    1.22 -                activeLoader = FnUtils.newLoader(impl, dfnr, myCls.getClassLoader().getParent());
    1.23              }
    1.24          }
    1.25          
     2.1 --- a/boot/src/main/java/org/netbeans/html/boot/impl/FnContext.java	Tue Mar 10 15:22:39 2015 +0100
     2.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/FnContext.java	Tue Mar 31 15:40:22 2015 +0200
     2.3 @@ -49,11 +49,11 @@
     2.4  import java.io.InputStreamReader;
     2.5  import java.io.PrintWriter;
     2.6  import java.io.StringWriter;
     2.7 +import java.lang.reflect.Method;
     2.8  import java.net.URL;
     2.9  import java.util.logging.Level;
    2.10  import java.util.logging.Logger;
    2.11  import org.netbeans.html.boot.spi.Fn;
    2.12 -import org.objectweb.asm.Opcodes;
    2.13  
    2.14  /**
    2.15   *
    2.16 @@ -74,16 +74,17 @@
    2.17          return l.getResource("META-INF/net.java.html.js.classes");
    2.18      }
    2.19  
    2.20 -    public static boolean isAsmPresent(URL res) {
    2.21 +    public static ClassLoader newLoader(URL res, FindResources impl, Fn.Presenter p, ClassLoader parent) {
    2.22          StringWriter w = new StringWriter();
    2.23          PrintWriter pw = new PrintWriter(w);
    2.24          Throwable t;
    2.25          try {
    2.26 -            Class.forName("org.objectweb.asm.Opcodes"); // NOI18N
    2.27 -            return true;
    2.28 +            Method newLoader = Class.forName("org.netbeans.html.boot.impl.FnUtils") // NOI18N
    2.29 +                .getMethod("newLoader", FindResources.class, Fn.Presenter.class, ClassLoader.class);
    2.30 +            return (ClassLoader) newLoader.invoke(null, impl, p, parent);
    2.31          } catch (LinkageError ex) {
    2.32              t = ex;
    2.33 -        } catch (ClassNotFoundException ex) {
    2.34 +        } catch (Exception ex) {
    2.35              t = ex;
    2.36          }
    2.37          pw.println("When using @JavaScriptBody methods, one needs to either:");
    2.38 @@ -108,7 +109,7 @@
    2.39          pw.println("Cannot initialize asm-5.0.jar!");
    2.40          pw.flush();
    2.41          LOG.log(Level.SEVERE, w.toString(), t);
    2.42 -        return false;
    2.43 +        return null;
    2.44      }
    2.45  
    2.46      private Object prev;
     3.1 --- a/boot/src/main/java/org/netbeans/html/boot/impl/FnUtils.java	Tue Mar 10 15:22:39 2015 +0100
     3.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/FnUtils.java	Tue Mar 31 15:40:22 2015 +0200
     3.3 @@ -42,6 +42,7 @@
     3.4   */
     3.5  package org.netbeans.html.boot.impl;
     3.6  
     3.7 +import java.io.IOException;
     3.8  import java.io.InputStream;
     3.9  import java.io.InputStreamReader;
    3.10  import java.io.Reader;
    3.11 @@ -65,7 +66,9 @@
    3.12  import org.objectweb.asm.signature.SignatureVisitor;
    3.13  import org.objectweb.asm.signature.SignatureWriter;
    3.14  
    3.15 -/**
    3.16 +/** Utilities related to bytecode transformations. Depend on asm.jar which
    3.17 + * needs to be added to be provided to classpath to make methods in this 
    3.18 + * class useful.
    3.19   *
    3.20   * @author Jaroslav Tulach
    3.21   */
    3.22 @@ -108,39 +111,8 @@
    3.23          return bytecode;
    3.24      }
    3.25      
    3.26 -    public static boolean isValid(Fn fn) {
    3.27 -        return fn != null && fn.isValid();
    3.28 -    }
    3.29 -
    3.30      public static ClassLoader newLoader(final FindResources f, final Fn.Presenter d, ClassLoader parent) {
    3.31 -        return new JsClassLoader(parent) {
    3.32 -            @Override
    3.33 -            protected URL findResource(String name) {
    3.34 -                List<URL> l = res(name, true);
    3.35 -                return l.isEmpty() ? null : l.get(0);
    3.36 -            }
    3.37 -            
    3.38 -            @Override
    3.39 -            protected Enumeration<URL> findResources(String name) {
    3.40 -                return Collections.enumeration(res(name, false));
    3.41 -            }
    3.42 -            
    3.43 -            private List<URL> res(String name, boolean oneIsEnough) {
    3.44 -                List<URL> l = new ArrayList<URL>();
    3.45 -                f.findResources(name, l, oneIsEnough);
    3.46 -                return l;
    3.47 -            }
    3.48 -            
    3.49 -            @Override
    3.50 -            protected Fn defineFn(String code, String... names) {
    3.51 -                return d.defineFn(code, names);
    3.52 -            }
    3.53 -
    3.54 -            @Override
    3.55 -            protected void loadScript(Reader code) throws Exception {
    3.56 -                d.loadScript(code);
    3.57 -            }
    3.58 -        };
    3.59 +        return new JsClassLoaderImpl(parent, f, d);
    3.60      }
    3.61  
    3.62      static String callback(final String body) {
    3.63 @@ -166,36 +138,13 @@
    3.64          }.parse(body);
    3.65      }
    3.66  
    3.67 -    static void loadScript(ClassLoader jcl, String resource) {
    3.68 -        final InputStream script = jcl.getResourceAsStream(resource);
    3.69 -        if (script == null) {
    3.70 -            throw new NullPointerException("Can't find " + resource);
    3.71 -        }
    3.72 -        try {
    3.73 -            Reader isr = null;
    3.74 -            try {
    3.75 -                isr = new InputStreamReader(script, "UTF-8");
    3.76 -                FnContext.currentPresenter(false).loadScript(isr);
    3.77 -            } finally {
    3.78 -                if (isr != null) {
    3.79 -                    isr.close();
    3.80 -                }
    3.81 -            }
    3.82 -        } catch (Exception ex) {
    3.83 -            throw new IllegalStateException("Can't execute " + resource, ex);
    3.84 -        } 
    3.85 -    }
    3.86 -    
    3.87 -    
    3.88      private static final class FindInClass extends ClassVisitor {
    3.89          private String name;
    3.90          private int found;
    3.91 -        private ClassLoader loader;
    3.92          private String resource;
    3.93  
    3.94          public FindInClass(ClassLoader l, ClassVisitor cv) {
    3.95              super(Opcodes.ASM4, cv);
    3.96 -            this.loader = l;
    3.97          }
    3.98  
    3.99          @Override
   3.100 @@ -596,7 +545,7 @@
   3.101  
   3.102      private static class ClassWriterEx extends ClassWriter {
   3.103  
   3.104 -        private ClassLoader loader;
   3.105 +        private final ClassLoader loader;
   3.106  
   3.107          public ClassWriterEx(ClassLoader l, ClassReader classReader, int flags) {
   3.108              super(classReader, flags);
   3.109 @@ -628,4 +577,117 @@
   3.110              }
   3.111          }
   3.112      }
   3.113 +
   3.114 +    static class JsClassLoaderImpl extends JsClassLoader {
   3.115 +
   3.116 +        private final FindResources f;
   3.117 +        private final Fn.Presenter d;
   3.118 +
   3.119 +        public JsClassLoaderImpl(ClassLoader parent, FindResources f, Fn.Presenter d) {
   3.120 +            super(parent);
   3.121 +            setDefaultAssertionStatus(JsClassLoader.class.desiredAssertionStatus());
   3.122 +            this.f = f;
   3.123 +            this.d = d;
   3.124 +        }
   3.125 +
   3.126 +        @Override
   3.127 +        protected URL findResource(String name) {
   3.128 +            List<URL> l = res(name, true);
   3.129 +            return l.isEmpty() ? null : l.get(0);
   3.130 +        }
   3.131 +
   3.132 +        @Override
   3.133 +        protected Enumeration<URL> findResources(String name) {
   3.134 +            return Collections.enumeration(res(name, false));
   3.135 +        }
   3.136 +        
   3.137 +        private List<URL> res(String name, boolean oneIsEnough) {
   3.138 +            List<URL> l = new ArrayList<URL>();
   3.139 +            f.findResources(name, l, oneIsEnough);
   3.140 +            return l;
   3.141 +        }
   3.142 +    
   3.143 +        @Override
   3.144 +        protected Class<?> findClass(String name) throws ClassNotFoundException {
   3.145 +            if (name.startsWith("javafx")) {
   3.146 +                return Class.forName(name);
   3.147 +            }
   3.148 +            if (name.startsWith("netscape")) {
   3.149 +                return Class.forName(name);
   3.150 +            }
   3.151 +            if (name.startsWith("com.sun")) {
   3.152 +                return Class.forName(name);
   3.153 +            }
   3.154 +            if (name.startsWith("org.netbeans.html.context.spi")) {
   3.155 +                return Class.forName(name);
   3.156 +            }
   3.157 +            if (name.startsWith("net.java.html.BrwsrCtx")) {
   3.158 +                return Class.forName(name);
   3.159 +            }
   3.160 +            if (name.equals(JsClassLoader.class.getName())) {
   3.161 +                return JsClassLoader.class;
   3.162 +            }
   3.163 +            if (name.equals(Fn.class.getName())) {
   3.164 +                return Fn.class;
   3.165 +            }
   3.166 +            if (name.equals(Fn.Presenter.class.getName())) {
   3.167 +                return Fn.Presenter.class;
   3.168 +            }
   3.169 +            if (name.equals(Fn.ToJavaScript.class.getName())) {
   3.170 +                return Fn.ToJavaScript.class;
   3.171 +            }
   3.172 +            if (name.equals(Fn.FromJavaScript.class.getName())) {
   3.173 +                return Fn.FromJavaScript.class;
   3.174 +            }
   3.175 +            if (name.equals(FnUtils.class.getName())) {
   3.176 +                return FnUtils.class;
   3.177 +            }
   3.178 +            if (
   3.179 +                name.equals("org.netbeans.html.boot.spi.Fn") ||
   3.180 +                name.equals("org.netbeans.html.boot.impl.FnUtils") ||
   3.181 +                name.equals("org.netbeans.html.boot.impl.FnContext")
   3.182 +            ) {
   3.183 +                return Class.forName(name);
   3.184 +            }
   3.185 +            URL u = findResource(name.replace('.', '/') + ".class");
   3.186 +            if (u != null) {
   3.187 +                InputStream is = null;
   3.188 +                try {
   3.189 +                    is = u.openStream();
   3.190 +                    byte[] arr = new byte[is.available()];
   3.191 +                    int len = 0;
   3.192 +                    while (len < arr.length) {
   3.193 +                        int read = is.read(arr, len, arr.length - len);
   3.194 +                        if (read == -1) {
   3.195 +                            throw new IOException("Can't read " + u);
   3.196 +                        }
   3.197 +                        len += read;
   3.198 +                    }
   3.199 +                    is.close();
   3.200 +                    is = null;
   3.201 +                    if (JsPkgCache.process(this, name)) {
   3.202 +                        arr = FnUtils.transform(arr, this);
   3.203 +                    }
   3.204 +                    return defineClass(name, arr, 0, arr.length);
   3.205 +                } catch (IOException ex) {
   3.206 +                    throw new ClassNotFoundException("Can't load " + name, ex);
   3.207 +                } finally {
   3.208 +                    try {
   3.209 +                        if (is != null) is.close();
   3.210 +                    } catch (IOException ex) {
   3.211 +                        throw new ClassNotFoundException(null, ex);
   3.212 +                    }
   3.213 +                }
   3.214 +            }
   3.215 +            return super.findClass(name);
   3.216 +        }
   3.217 +    
   3.218 +        protected Fn defineFn(String code, String... names) {
   3.219 +            return d.defineFn(code, names);
   3.220 +        }
   3.221 +        
   3.222 +        protected void loadScript(Reader code) throws Exception {
   3.223 +            d.loadScript(code);
   3.224 +        }
   3.225 +    }
   3.226  }
     4.1 --- a/boot/src/main/java/org/netbeans/html/boot/impl/JsClassLoader.java	Tue Mar 10 15:22:39 2015 +0100
     4.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/JsClassLoader.java	Tue Mar 31 15:40:22 2015 +0200
     4.3 @@ -42,14 +42,10 @@
     4.4   */
     4.5  package org.netbeans.html.boot.impl;
     4.6  
     4.7 -import org.netbeans.html.boot.spi.Fn;
     4.8 -import java.io.IOException;
     4.9 -import java.io.InputStream;
    4.10 -import java.io.Reader;
    4.11 -import java.net.URL;
    4.12 -import java.util.Enumeration;
    4.13 +import net.java.html.js.JavaScriptBody;
    4.14  
    4.15 -/** 
    4.16 +/** Marker class to help us recognize we assigned classloader is
    4.17 + * capable to handle {@link JavaScriptBody} annotated methods.
    4.18   *
    4.19   * @author Jaroslav Tulach
    4.20   */
    4.21 @@ -58,88 +54,4 @@
    4.22          super(parent);
    4.23          setDefaultAssertionStatus(JsClassLoader.class.desiredAssertionStatus());
    4.24      }
    4.25 -    
    4.26 -    @Override
    4.27 -    protected abstract URL findResource(String name);
    4.28 -    
    4.29 -    @Override
    4.30 -    protected abstract Enumeration<URL> findResources(String name);
    4.31 -
    4.32 -    @Override
    4.33 -    protected Class<?> findClass(String name) throws ClassNotFoundException {
    4.34 -        if (name.startsWith("javafx")) {
    4.35 -            return Class.forName(name);
    4.36 -        }
    4.37 -        if (name.startsWith("netscape")) {
    4.38 -            return Class.forName(name);
    4.39 -        }
    4.40 -        if (name.startsWith("com.sun")) {
    4.41 -            return Class.forName(name);
    4.42 -        }
    4.43 -        if (name.startsWith("org.netbeans.html.context.spi")) {
    4.44 -            return Class.forName(name);
    4.45 -        }
    4.46 -        if (name.startsWith("net.java.html.BrwsrCtx")) {
    4.47 -            return Class.forName(name);
    4.48 -        }
    4.49 -        if (name.equals(JsClassLoader.class.getName())) {
    4.50 -            return JsClassLoader.class;
    4.51 -        }
    4.52 -        if (name.equals(Fn.class.getName())) {
    4.53 -            return Fn.class;
    4.54 -        }
    4.55 -        if (name.equals(Fn.Presenter.class.getName())) {
    4.56 -            return Fn.Presenter.class;
    4.57 -        }
    4.58 -        if (name.equals(Fn.ToJavaScript.class.getName())) {
    4.59 -            return Fn.ToJavaScript.class;
    4.60 -        }
    4.61 -        if (name.equals(Fn.FromJavaScript.class.getName())) {
    4.62 -            return Fn.FromJavaScript.class;
    4.63 -        }
    4.64 -        if (name.equals(FnUtils.class.getName())) {
    4.65 -            return FnUtils.class;
    4.66 -        }
    4.67 -        if (
    4.68 -            name.equals("org.netbeans.html.boot.spi.Fn") ||
    4.69 -            name.equals("org.netbeans.html.boot.impl.FnUtils") ||
    4.70 -            name.equals("org.netbeans.html.boot.impl.FnContext")
    4.71 -        ) {
    4.72 -            return Class.forName(name);
    4.73 -        }
    4.74 -        URL u = findResource(name.replace('.', '/') + ".class");
    4.75 -        if (u != null) {
    4.76 -            InputStream is = null;
    4.77 -            try {
    4.78 -                is = u.openStream();
    4.79 -                byte[] arr = new byte[is.available()];
    4.80 -                int len = 0;
    4.81 -                while (len < arr.length) {
    4.82 -                    int read = is.read(arr, len, arr.length - len);
    4.83 -                    if (read == -1) {
    4.84 -                        throw new IOException("Can't read " + u);
    4.85 -                    }
    4.86 -                    len += read;
    4.87 -                }
    4.88 -                is.close();
    4.89 -                is = null;
    4.90 -                if (JsPkgCache.process(this, name)) {
    4.91 -                    arr = FnUtils.transform(arr, JsClassLoader.this);
    4.92 -                }
    4.93 -                return defineClass(name, arr, 0, arr.length);
    4.94 -            } catch (IOException ex) {
    4.95 -                throw new ClassNotFoundException("Can't load " + name, ex);
    4.96 -            } finally {
    4.97 -                try {
    4.98 -                    if (is != null) is.close();
    4.99 -                } catch (IOException ex) {
   4.100 -                    throw new ClassNotFoundException(null, ex);
   4.101 -                }
   4.102 -            }
   4.103 -        }
   4.104 -        return super.findClass(name);
   4.105 -    }
   4.106 -    
   4.107 -    protected abstract Fn defineFn(String code, String... names);
   4.108 -    protected abstract void loadScript(Reader code) throws Exception;
   4.109  }
     5.1 --- a/boot/src/test/java/org/netbeans/html/boot/impl/JsClassLoaderTest.java	Tue Mar 10 15:22:39 2015 +0100
     5.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/JsClassLoaderTest.java	Tue Mar 31 15:40:22 2015 +0200
     5.3 @@ -75,10 +75,10 @@
     5.4          final URL my = JsClassLoaderTest.class.getProtectionDomain().getCodeSource().getLocation();
     5.5          ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
     5.6          final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
     5.7 -        class MyCL extends JsClassLoader implements Fn.Presenter {
     5.8 +        class MyCL extends FnUtils.JsClassLoaderImpl implements Fn.Presenter {
     5.9  
    5.10              public MyCL(ClassLoader parent) {
    5.11 -                super(parent);
    5.12 +                super(parent, null, null);
    5.13              }
    5.14              
    5.15              @Override