jaroslav@1041: /** jaroslav@1041: * Back 2 Browser Bytecode Translator jaroslav@1041: * Copyright (C) 2012 Jaroslav Tulach jaroslav@1041: * jaroslav@1041: * This program is free software: you can redistribute it and/or modify jaroslav@1041: * it under the terms of the GNU General Public License as published by jaroslav@1041: * the Free Software Foundation, version 2 of the License. jaroslav@1041: * jaroslav@1041: * This program is distributed in the hope that it will be useful, jaroslav@1041: * but WITHOUT ANY WARRANTY; without even the implied warranty of jaroslav@1041: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the jaroslav@1041: * GNU General Public License for more details. jaroslav@1041: * jaroslav@1041: * You should have received a copy of the GNU General Public License jaroslav@1041: * along with this program. Look for COPYING file in the top folder. jaroslav@1041: * If not, see http://opensource.org/licenses/GPL-2.0. jaroslav@1041: */ jaroslav@1041: package org.apidesign.bck2brwsr.launcher.fximpl; jaroslav@1041: jaroslav@1174: import java.net.URL; jaroslav@1175: import java.util.ArrayList; jaroslav@1175: import java.util.Collections; jaroslav@1175: import java.util.Enumeration; jaroslav@1175: import java.util.List; jaroslav@1041: import java.util.TooManyListenersException; jaroslav@1041: import javafx.beans.value.ChangeListener; jaroslav@1174: import javafx.scene.web.WebEngine; jaroslav@1174: import netscape.javascript.JSObject; jaroslav@1041: jaroslav@1041: /** jaroslav@1041: * jaroslav@1041: * @author Jaroslav Tulach jaroslav@1041: */ jaroslav@1041: public final class JVMBridge { jaroslav@1174: private final WebEngine engine; jaroslav@1174: private final WebClassLoader cl; jaroslav@1174: jaroslav@1041: private static ClassLoader[] ldrs; jaroslav@1041: private static ChangeListener onBck2BrwsrLoad; jaroslav@1174: jaroslav@1174: JVMBridge(WebEngine eng) { jaroslav@1174: this.engine = eng; jaroslav@1179: this.cl = new WebClassLoader(JVMBridge.class.getClassLoader().getParent()); jaroslav@1174: } jaroslav@1041: jaroslav@1041: public static void registerClassLoaders(ClassLoader[] loaders) { jaroslav@1041: ldrs = loaders.clone(); jaroslav@1041: } jaroslav@1041: jaroslav@1041: public static void addBck2BrwsrLoad(ChangeListener l) throws TooManyListenersException { jaroslav@1041: if (onBck2BrwsrLoad != null) { jaroslav@1041: throw new TooManyListenersException(); jaroslav@1041: } jaroslav@1041: onBck2BrwsrLoad = l; jaroslav@1041: } jaroslav@1041: jaroslav@1041: public static void onBck2BrwsrLoad() { jaroslav@1041: ChangeListener l = onBck2BrwsrLoad; jaroslav@1041: if (l != null) { jaroslav@1041: l.changed(null, null, null); jaroslav@1041: } jaroslav@1041: } jaroslav@1041: jaroslav@1041: public Class loadClass(String name) throws ClassNotFoundException { jaroslav@1174: return Class.forName(name, true, cl); jaroslav@1174: } jaroslav@1174: jaroslav@1174: private final class WebClassLoader extends JsClassLoader { jaroslav@1174: public WebClassLoader(ClassLoader parent) { jaroslav@1174: super(parent); jaroslav@1174: } jaroslav@1174: jaroslav@1174: @Override jaroslav@1174: protected URL findResource(String name) { jaroslav@1174: if (ldrs != null) for (ClassLoader l : ldrs) { jaroslav@1174: URL u = l.getResource(name); jaroslav@1174: if (u != null) { jaroslav@1174: return u; jaroslav@1174: } jaroslav@1041: } jaroslav@1174: return null; jaroslav@1041: } jaroslav@1175: jaroslav@1175: @Override jaroslav@1175: protected Enumeration findResources(String name) { jaroslav@1175: List arr = new ArrayList(); jaroslav@1175: if (ldrs != null) { jaroslav@1175: for (ClassLoader l : ldrs) { jaroslav@1175: URL u = l.getResource(name); jaroslav@1175: if (u != null) { jaroslav@1175: arr.add(u); jaroslav@1175: } jaroslav@1175: } jaroslav@1175: } jaroslav@1175: return Collections.enumeration(arr); jaroslav@1175: } jaroslav@1174: jaroslav@1174: @Override jaroslav@1174: protected Fn defineFn(String code, String... names) { jaroslav@1174: StringBuilder sb = new StringBuilder(); jaroslav@1174: sb.append("(function() {"); jaroslav@1174: sb.append(" var x = {};"); jaroslav@1174: sb.append(" x.fn = function("); jaroslav@1174: String sep = ""; jaroslav@1174: for (String n : names) { jaroslav@1174: sb.append(sep).append(n); jaroslav@1174: sep = ","; jaroslav@1174: } jaroslav@1174: sb.append(") {\n"); jaroslav@1174: sb.append(code); jaroslav@1174: sb.append("};"); jaroslav@1174: sb.append("return x;"); jaroslav@1174: sb.append("})()"); jaroslav@1174: jaroslav@1174: JSObject x = (JSObject) engine.executeScript(sb.toString()); jaroslav@1174: return new JSFn(x); jaroslav@1041: } jaroslav@1174: } jaroslav@1174: jaroslav@1174: private static final class JSFn extends Fn { jaroslav@1174: private final JSObject fn; jaroslav@1174: jaroslav@1174: public JSFn(JSObject fn) { jaroslav@1174: this.fn = fn; jaroslav@1174: } jaroslav@1174: jaroslav@1174: @Override jaroslav@1181: public Object invoke(Object thiz, Object... args) throws Exception { jaroslav@1179: try { jaroslav@1179: return fn.call("fn", args); // NOI18N jaroslav@1179: } catch (Error t) { jaroslav@1179: t.printStackTrace(); jaroslav@1179: throw t; jaroslav@1179: } catch (Exception t) { jaroslav@1179: t.printStackTrace(); jaroslav@1179: throw t; jaroslav@1179: } jaroslav@1174: } jaroslav@1041: } jaroslav@1041: }