launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JVMBridge.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 17 Jun 2013 19:55:31 +0200
branchclassloader
changeset 1183 29302b4c0776
parent 1181 b703d9d71f25
child 1184 ccf2447021f6
permissions -rw-r--r--
Using the same trick with call also inside WebView
     1 /**
     2  * Back 2 Browser Bytecode Translator
     3  * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4  *
     5  * This program is free software: you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation, version 2 of the License.
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program. Look for COPYING file in the top folder.
    16  * If not, see http://opensource.org/licenses/GPL-2.0.
    17  */
    18 package org.apidesign.bck2brwsr.launcher.fximpl;
    19 
    20 import java.net.URL;
    21 import java.util.ArrayList;
    22 import java.util.Arrays;
    23 import java.util.Collections;
    24 import java.util.Enumeration;
    25 import java.util.List;
    26 import java.util.TooManyListenersException;
    27 import javafx.beans.value.ChangeListener;
    28 import javafx.scene.web.WebEngine;
    29 import javax.script.Invocable;
    30 import netscape.javascript.JSObject;
    31 
    32 /**
    33  *
    34  * @author Jaroslav Tulach <jtulach@netbeans.org>
    35  */
    36 public final class JVMBridge {
    37     private final WebEngine engine;
    38     private final WebClassLoader cl;
    39     
    40     private static ClassLoader[] ldrs;
    41     private static ChangeListener<Void> onBck2BrwsrLoad;
    42     
    43     JVMBridge(WebEngine eng) {
    44         this.engine = eng;
    45         this.cl = new WebClassLoader(JVMBridge.class.getClassLoader().getParent());
    46     }
    47         
    48     public static void registerClassLoaders(ClassLoader[] loaders) {
    49         ldrs = loaders.clone();
    50     }
    51     
    52     public static void addBck2BrwsrLoad(ChangeListener<Void> l) throws TooManyListenersException {
    53         if (onBck2BrwsrLoad != null) {
    54             throw new TooManyListenersException();
    55         }
    56         onBck2BrwsrLoad = l;
    57     }
    58 
    59     public static void onBck2BrwsrLoad() {
    60         ChangeListener<Void> l = onBck2BrwsrLoad;
    61         if (l != null) {
    62             l.changed(null, null, null);
    63         }
    64     }
    65     
    66     public Class<?> loadClass(String name) throws ClassNotFoundException {
    67         return Class.forName(name, true, cl);
    68     }
    69     
    70     private final class WebClassLoader extends JsClassLoader {
    71         public WebClassLoader(ClassLoader parent) {
    72             super(parent);
    73         }
    74 
    75         @Override
    76         protected URL findResource(String name) {
    77             if (ldrs != null) for (ClassLoader l : ldrs) {
    78                 URL u = l.getResource(name);
    79                 if (u != null) {
    80                     return u;
    81                 }
    82             }
    83             return null;
    84         }
    85         
    86         @Override
    87         protected Enumeration<URL> findResources(String name) {
    88             List<URL> arr = new ArrayList<URL>();
    89             if (ldrs != null) {
    90                 for (ClassLoader l : ldrs) {
    91                     URL u = l.getResource(name);
    92                     if (u != null) {
    93                         arr.add(u);
    94                     }
    95                 }
    96             }
    97             return Collections.enumeration(arr);
    98         }
    99 
   100         @Override
   101         protected Fn defineFn(String code, String... names) {
   102             StringBuilder sb = new StringBuilder();
   103             sb.append("(function() {");
   104             sb.append("  return function(");
   105             String sep = "";
   106             for (String n : names) {
   107                 sb.append(sep).append(n);
   108                 sep = ",";
   109             }
   110             sb.append(") {\n");
   111             sb.append(code);
   112             sb.append("};");
   113             sb.append("})()");
   114             
   115             JSObject x = (JSObject) engine.executeScript(sb.toString());
   116             return new JSFn(x);
   117         }
   118     }
   119     
   120     private static final class JSFn extends Fn {
   121         private final JSObject fn;
   122 
   123         public JSFn(JSObject fn) {
   124             this.fn = fn;
   125         }
   126         
   127         @Override
   128         public Object invoke(Object thiz, Object... args) throws Exception {
   129             try {
   130                 List<Object> all = new ArrayList<Object>(args.length + 1);
   131                 all.add(thiz == null ? fn : thiz);
   132                 all.addAll(Arrays.asList(args));
   133                 Object ret = fn.call("call", all.toArray()); // NOI18N
   134                 return ret == fn ? null : ret;
   135             } catch (Error t) {
   136                 t.printStackTrace();
   137                 throw t;
   138             } catch (Exception t) {
   139                 t.printStackTrace();
   140                 throw t;
   141             }
   142         }
   143     }
   144 }