#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
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