Trying to use JsClassLoader in FX launcher classloader
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Wed, 12 Jun 2013 18:19:29 +0200
branchclassloader
changeset 1174f78cdceed17b
parent 1172 c04c43d5fdc6
child 1175 15c6903c8612
Trying to use JsClassLoader in FX launcher
launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/FXBrwsr.java
launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JVMBridge.java
launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JsClassLoader.java
launcher/fx/src/test/java/org/apidesign/bck2brwsr/launcher/fximpl/JsClassLoaderTest.java
     1.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/FXBrwsr.java	Tue Jun 11 09:13:33 2013 +0200
     1.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/FXBrwsr.java	Wed Jun 12 18:19:29 2013 +0200
     1.3 @@ -89,11 +89,12 @@
     1.4       * Create a resizable WebView pane
     1.5       */
     1.6      private static class WebController {
     1.7 -        private final JVMBridge bridge = new JVMBridge();
     1.8 +        private final JVMBridge bridge;
     1.9          private final WebDebug dbg;
    1.10          private final String ud;
    1.11  
    1.12          public WebController(WebView view, String ud, List<String> params) {
    1.13 +            this.bridge = new JVMBridge(view.getEngine());
    1.14              this.ud = ud;
    1.15              LOG.log(Level.INFO, "Initializing WebView with {0}", params);
    1.16              final WebEngine eng = view.getEngine();
     2.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JVMBridge.java	Tue Jun 11 09:13:33 2013 +0200
     2.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JVMBridge.java	Wed Jun 12 18:19:29 2013 +0200
     2.3 @@ -17,16 +17,27 @@
     2.4   */
     2.5  package org.apidesign.bck2brwsr.launcher.fximpl;
     2.6  
     2.7 +import java.net.URL;
     2.8  import java.util.TooManyListenersException;
     2.9  import javafx.beans.value.ChangeListener;
    2.10 +import javafx.scene.web.WebEngine;
    2.11 +import netscape.javascript.JSObject;
    2.12  
    2.13  /**
    2.14   *
    2.15   * @author Jaroslav Tulach <jtulach@netbeans.org>
    2.16   */
    2.17  public final class JVMBridge {
    2.18 +    private final WebEngine engine;
    2.19 +    private final WebClassLoader cl;
    2.20 +    
    2.21      private static ClassLoader[] ldrs;
    2.22      private static ChangeListener<Void> onBck2BrwsrLoad;
    2.23 +    
    2.24 +    JVMBridge(WebEngine eng) {
    2.25 +        this.engine = eng;
    2.26 +        this.cl = new WebClassLoader(JVMBridge.class.getClassLoader());
    2.27 +    }
    2.28          
    2.29      public static void registerClassLoaders(ClassLoader[] loaders) {
    2.30          ldrs = loaders.clone();
    2.31 @@ -47,18 +58,57 @@
    2.32      }
    2.33      
    2.34      public Class<?> loadClass(String name) throws ClassNotFoundException {
    2.35 -        System.err.println("trying to load " + name);
    2.36 -        ClassNotFoundException ex = null;
    2.37 -        if (ldrs != null) for (ClassLoader l : ldrs) {
    2.38 -            try {
    2.39 -                return Class.forName(name, true, l);
    2.40 -            } catch (ClassNotFoundException ex2) {
    2.41 -                ex = ex2;
    2.42 +        return Class.forName(name, true, cl);
    2.43 +    }
    2.44 +    
    2.45 +    private final class WebClassLoader extends JsClassLoader {
    2.46 +        public WebClassLoader(ClassLoader parent) {
    2.47 +            super(parent);
    2.48 +        }
    2.49 +
    2.50 +        @Override
    2.51 +        protected URL findResource(String name) {
    2.52 +            if (ldrs != null) for (ClassLoader l : ldrs) {
    2.53 +                URL u = l.getResource(name);
    2.54 +                if (u != null) {
    2.55 +                    return u;
    2.56 +                }
    2.57              }
    2.58 +            return null;
    2.59          }
    2.60 -        if (ex == null) {
    2.61 -            ex = new ClassNotFoundException("No loaders");
    2.62 +
    2.63 +        @Override
    2.64 +        protected Fn defineFn(String code, String... names) {
    2.65 +            StringBuilder sb = new StringBuilder();
    2.66 +            sb.append("(function() {");
    2.67 +            sb.append("  var x = {};");
    2.68 +            sb.append("  x.fn = function(");
    2.69 +            String sep = "";
    2.70 +            for (String n : names) {
    2.71 +                sb.append(sep).append(n);
    2.72 +                sep = ",";
    2.73 +            }
    2.74 +            sb.append(") {\n");
    2.75 +            sb.append(code);
    2.76 +            sb.append("};");
    2.77 +            sb.append("return x;");
    2.78 +            sb.append("})()");
    2.79 +            
    2.80 +            JSObject x = (JSObject) engine.executeScript(sb.toString());
    2.81 +            return new JSFn(x);
    2.82          }
    2.83 -        throw ex;
    2.84 +    }
    2.85 +    
    2.86 +    private static final class JSFn extends Fn {
    2.87 +        private final JSObject fn;
    2.88 +
    2.89 +        public JSFn(JSObject fn) {
    2.90 +            this.fn = fn;
    2.91 +        }
    2.92 +        
    2.93 +        @Override
    2.94 +        public Object invoke(Object... args) throws Exception {
    2.95 +            return fn.call("fn", args); // NOI18N
    2.96 +        }
    2.97      }
    2.98  }
     3.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JsClassLoader.java	Tue Jun 11 09:13:33 2013 +0200
     3.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JsClassLoader.java	Wed Jun 12 18:19:29 2013 +0200
     3.3 @@ -38,10 +38,13 @@
     3.4   *
     3.5   * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     3.6   */
     3.7 -abstract class JsClassLoader extends URLClassLoader {
     3.8 -    JsClassLoader(URL[] urls, ClassLoader parent) {
     3.9 -        super(urls, parent);
    3.10 +abstract class JsClassLoader extends ClassLoader {
    3.11 +    JsClassLoader(ClassLoader parent) {
    3.12 +        super(parent);
    3.13      }
    3.14 +    
    3.15 +    @Override
    3.16 +    protected abstract URL findResource(String name);
    3.17  
    3.18      @Override
    3.19      protected Class<?> findClass(String name) throws ClassNotFoundException {
     4.1 --- a/launcher/fx/src/test/java/org/apidesign/bck2brwsr/launcher/fximpl/JsClassLoaderTest.java	Tue Jun 11 09:13:33 2013 +0200
     4.2 +++ b/launcher/fx/src/test/java/org/apidesign/bck2brwsr/launcher/fximpl/JsClassLoaderTest.java	Wed Jun 12 18:19:29 2013 +0200
     4.3 @@ -20,6 +20,7 @@
     4.4  import java.lang.reflect.InvocationTargetException;
     4.5  import java.lang.reflect.Method;
     4.6  import java.net.URL;
     4.7 +import java.net.URLClassLoader;
     4.8  import javax.script.Invocable;
     4.9  import javax.script.ScriptEngine;
    4.10  import javax.script.ScriptEngineManager;
    4.11 @@ -45,9 +46,14 @@
    4.12          ScriptEngineManager sem = new ScriptEngineManager();
    4.13          final ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
    4.14          
    4.15 -        URL my = JsClassLoaderTest.class.getProtectionDomain().getCodeSource().getLocation();
    4.16 +        final URL my = JsClassLoaderTest.class.getProtectionDomain().getCodeSource().getLocation();
    4.17          ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
    4.18 -        loader = new JsClassLoader(new URL[] { my }, parent) {
    4.19 +        final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
    4.20 +        loader = new JsClassLoader(parent) {
    4.21 +            @Override
    4.22 +            protected URL findResource(String name) {
    4.23 +                return ul.getResource(name);
    4.24 +            }
    4.25              @Override
    4.26              protected Fn defineFn(String code, String... names) {
    4.27                  StringBuilder sb = new StringBuilder();