launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JVMBridge.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Wed, 26 Jun 2013 18:44:21 +0200
branchclassloader
changeset 1227 5a907f38608d
parent 1187 ce6327094088
child 1233 43fba26ba0c0
permissions -rw-r--r--
Successfully compiles the new support for knockout
     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.io.Reader;
    21 import org.apidesign.html.boot.spi.Fn;
    22 import java.net.URL;
    23 import java.util.ArrayList;
    24 import java.util.Arrays;
    25 import java.util.Collection;
    26 import java.util.List;
    27 import java.util.TooManyListenersException;
    28 import javafx.beans.value.ChangeListener;
    29 import javafx.scene.web.WebEngine;
    30 import netscape.javascript.JSObject;
    31 import org.apidesign.html.boot.impl.FindResources;
    32 import org.apidesign.html.boot.impl.FnUtils;
    33 
    34 /**
    35  *
    36  * @author Jaroslav Tulach <jtulach@netbeans.org>
    37  */
    38 public final class JVMBridge {
    39     private final WebEngine engine;
    40     private final ClassLoader cl;
    41     
    42     private static ClassLoader[] ldrs;
    43     private static ChangeListener<Void> onBck2BrwsrLoad;
    44     
    45     JVMBridge(WebEngine eng) {
    46         this.engine = eng;
    47         final ClassLoader p = JVMBridge.class.getClassLoader().getParent();
    48         WebClassLoader wcl = new WebClassLoader();
    49         this.cl = FnUtils.newLoader(wcl, wcl, p);
    50     }
    51         
    52     public static void registerClassLoaders(ClassLoader[] loaders) {
    53         ldrs = loaders.clone();
    54     }
    55     
    56     public static void addBck2BrwsrLoad(ChangeListener<Void> l) throws TooManyListenersException {
    57         if (onBck2BrwsrLoad != null) {
    58             throw new TooManyListenersException();
    59         }
    60         onBck2BrwsrLoad = l;
    61     }
    62 
    63     public static void onBck2BrwsrLoad() {
    64         ChangeListener<Void> l = onBck2BrwsrLoad;
    65         if (l != null) {
    66             l.changed(null, null, null);
    67         }
    68     }
    69     
    70     public Class<?> loadClass(String name) throws ClassNotFoundException {
    71         return Class.forName(name, true, cl);
    72     }
    73     
    74     private final class WebClassLoader implements FindResources, Fn.Presenter {
    75         @Override
    76         public void findResources(String name, Collection<? super URL> results, boolean oneIsEnough) {
    77             if (ldrs != null) for (ClassLoader l : ldrs) {
    78                 URL u = l.getResource(name);
    79                 if (u != null) {
    80                     results.add(u);
    81                 }
    82             }
    83         }
    84 
    85         @Override
    86         public Fn defineFn(String code, String... names) {
    87             StringBuilder sb = new StringBuilder();
    88             sb.append("(function() {");
    89             sb.append("  return function(");
    90             String sep = "";
    91             for (String n : names) {
    92                 sb.append(sep).append(n);
    93                 sep = ",";
    94             }
    95             sb.append(") {\n");
    96             sb.append(code);
    97             sb.append("};");
    98             sb.append("})()");
    99             
   100             JSObject x = (JSObject) engine.executeScript(sb.toString());
   101             return new JSFn(x);
   102         }
   103 
   104         @Override
   105         public void displayPage(URL page, Runnable onPageLoad) {
   106             throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
   107         }
   108 
   109         @Override
   110         public void loadScript(Reader code) throws Exception {
   111             throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
   112         }
   113     }
   114     
   115     private static final class JSFn extends Fn {
   116         private final JSObject fn;
   117 
   118         public JSFn(JSObject fn) {
   119             this.fn = fn;
   120         }
   121         
   122         @Override
   123         public Object invoke(Object thiz, Object... args) throws Exception {
   124             try {
   125                 List<Object> all = new ArrayList<Object>(args.length + 1);
   126                 all.add(thiz == null ? fn : thiz);
   127                 all.addAll(Arrays.asList(args));
   128                 Object ret = fn.call("call", all.toArray()); // NOI18N
   129                 return ret == fn ? null : ret;
   130             } catch (Error t) {
   131                 t.printStackTrace();
   132                 throw t;
   133             } catch (Exception t) {
   134                 t.printStackTrace();
   135                 throw t;
   136             }
   137         }
   138     }
   139 }