New classloader can be used to load the twitter application classloader
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 13 Jun 2013 16:48:17 +0200
branchclassloader
changeset 117515c6903c8612
parent 1174 f78cdceed17b
child 1176 0250b8a739de
New classloader can be used to load the twitter application
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/JVMBridge.java	Wed Jun 12 18:19:29 2013 +0200
     1.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JVMBridge.java	Thu Jun 13 16:48:17 2013 +0200
     1.3 @@ -18,6 +18,10 @@
     1.4  package org.apidesign.bck2brwsr.launcher.fximpl;
     1.5  
     1.6  import java.net.URL;
     1.7 +import java.util.ArrayList;
     1.8 +import java.util.Collections;
     1.9 +import java.util.Enumeration;
    1.10 +import java.util.List;
    1.11  import java.util.TooManyListenersException;
    1.12  import javafx.beans.value.ChangeListener;
    1.13  import javafx.scene.web.WebEngine;
    1.14 @@ -76,6 +80,20 @@
    1.15              }
    1.16              return null;
    1.17          }
    1.18 +        
    1.19 +        @Override
    1.20 +        protected Enumeration<URL> findResources(String name) {
    1.21 +            List<URL> arr = new ArrayList<URL>();
    1.22 +            if (ldrs != null) {
    1.23 +                for (ClassLoader l : ldrs) {
    1.24 +                    URL u = l.getResource(name);
    1.25 +                    if (u != null) {
    1.26 +                        arr.add(u);
    1.27 +                    }
    1.28 +                }
    1.29 +            }
    1.30 +            return Collections.enumeration(arr);
    1.31 +        }
    1.32  
    1.33          @Override
    1.34          protected Fn defineFn(String code, String... names) {
     2.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JsClassLoader.java	Wed Jun 12 18:19:29 2013 +0200
     2.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JsClassLoader.java	Thu Jun 13 16:48:17 2013 +0200
     2.3 @@ -20,8 +20,9 @@
     2.4  import java.io.IOException;
     2.5  import java.io.InputStream;
     2.6  import java.net.URL;
     2.7 -import java.net.URLClassLoader;
     2.8 +import java.net.URLConnection;
     2.9  import java.util.ArrayList;
    2.10 +import java.util.Enumeration;
    2.11  import java.util.List;
    2.12  import org.objectweb.asm.AnnotationVisitor;
    2.13  import org.objectweb.asm.ClassReader;
    2.14 @@ -45,6 +46,9 @@
    2.15      
    2.16      @Override
    2.17      protected abstract URL findResource(String name);
    2.18 +    
    2.19 +    @Override
    2.20 +    protected abstract Enumeration<URL> findResources(String name);
    2.21  
    2.22      @Override
    2.23      protected Class<?> findClass(String name) throws ClassNotFoundException {
    2.24 @@ -53,12 +57,25 @@
    2.25              InputStream is = null;
    2.26              try {
    2.27                  is = u.openStream();
    2.28 -                ClassReader cr = new ClassReader(is);
    2.29 -                ClassWriter w = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
    2.30 -                FindInClass fic = new FindInClass(w);
    2.31 -                cr.accept(fic, 0);
    2.32 -                byte[] arr = w.toByteArray();
    2.33 -                return defineClass(name, arr, 0, arr.length);
    2.34 +                byte[] arr = new byte[is.available()];
    2.35 +                int len = is.read(arr);
    2.36 +                if (len != arr.length) {
    2.37 +                    arr = null;
    2.38 +                }
    2.39 +                is.close();
    2.40 +                is = null;
    2.41 +                ClassReader cr = new ClassReader(arr);
    2.42 +                FindInClass tst = new FindInClass(null);
    2.43 +                cr.accept(tst, 0);
    2.44 +                if (tst.found) {
    2.45 +                    ClassWriter w = new ClassWriterEx(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
    2.46 +                    FindInClass fic = new FindInClass(w);
    2.47 +                    cr.accept(fic, 0);
    2.48 +                    arr = w.toByteArray();
    2.49 +                }
    2.50 +                if (arr != null) {
    2.51 +                    return defineClass(name, arr, 0, arr.length);
    2.52 +                }
    2.53              } catch (IOException ex) {
    2.54                  throw new ClassNotFoundException("Can't load " + name, ex);
    2.55              } finally {
    2.56 @@ -81,6 +98,7 @@
    2.57      
    2.58      private static final class FindInClass extends ClassVisitor {
    2.59          private String name;
    2.60 +        private boolean found;
    2.61          
    2.62          public FindInClass(ClassVisitor cv) {
    2.63              super(Opcodes.ASM4, cv);
    2.64 @@ -116,6 +134,7 @@
    2.65              @Override
    2.66              public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
    2.67                  if ("Lorg/apidesign/bck2brwsr/core/JavaScriptBody;".equals(desc)) { // NOI18N
    2.68 +                    found = true;
    2.69                      return new FindInAnno();
    2.70                  }
    2.71                  return super.visitAnnotation(desc, visible);
    2.72 @@ -297,4 +316,37 @@
    2.73              }
    2.74          }
    2.75      }
    2.76 +    
    2.77 +    private class ClassWriterEx extends ClassWriter {
    2.78 +
    2.79 +        public ClassWriterEx(ClassReader classReader, int flags) {
    2.80 +            super(classReader, flags);
    2.81 +        }
    2.82 +        
    2.83 +        @Override
    2.84 +        protected String getCommonSuperClass(final String type1, final String type2) {
    2.85 +            Class<?> c, d;
    2.86 +            ClassLoader classLoader = JsClassLoader.this;
    2.87 +            try {
    2.88 +                c = Class.forName(type1.replace('/', '.'), false, classLoader);
    2.89 +                d = Class.forName(type2.replace('/', '.'), false, classLoader);
    2.90 +            } catch (Exception e) {
    2.91 +                throw new RuntimeException(e.toString());
    2.92 +            }
    2.93 +            if (c.isAssignableFrom(d)) {
    2.94 +                return type1;
    2.95 +            }
    2.96 +            if (d.isAssignableFrom(c)) {
    2.97 +                return type2;
    2.98 +            }
    2.99 +            if (c.isInterface() || d.isInterface()) {
   2.100 +                return "java/lang/Object";
   2.101 +            } else {
   2.102 +                do {
   2.103 +                    c = c.getSuperclass();
   2.104 +                } while (!c.isAssignableFrom(d));
   2.105 +                return c.getName().replace('.', '/');
   2.106 +            }
   2.107 +        }        
   2.108 +    }
   2.109  }
     3.1 --- a/launcher/fx/src/test/java/org/apidesign/bck2brwsr/launcher/fximpl/JsClassLoaderTest.java	Wed Jun 12 18:19:29 2013 +0200
     3.2 +++ b/launcher/fx/src/test/java/org/apidesign/bck2brwsr/launcher/fximpl/JsClassLoaderTest.java	Thu Jun 13 16:48:17 2013 +0200
     3.3 @@ -21,6 +21,7 @@
     3.4  import java.lang.reflect.Method;
     3.5  import java.net.URL;
     3.6  import java.net.URLClassLoader;
     3.7 +import java.util.Enumeration;
     3.8  import javax.script.Invocable;
     3.9  import javax.script.ScriptEngine;
    3.10  import javax.script.ScriptEngineManager;
    3.11 @@ -84,6 +85,11 @@
    3.12                      throw new LinkageError("Can't parse: " + sb, ex);
    3.13                  }
    3.14              }
    3.15 +
    3.16 +            @Override
    3.17 +            protected Enumeration<URL> findResources(String name) {
    3.18 +                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    3.19 +            }
    3.20          };
    3.21          
    3.22          methodClass = loader.loadClass(JsMethods.class.getName());