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@1233: import java.io.BufferedReader; jaroslav@1227: import java.io.Reader; jaroslav@1184: import org.apidesign.html.boot.spi.Fn; jaroslav@1174: import java.net.URL; jaroslav@1175: import java.util.ArrayList; jaroslav@1183: import java.util.Arrays; jaroslav@1184: import java.util.Collection; 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@1184: import org.apidesign.html.boot.impl.FindResources; jaroslav@1184: import org.apidesign.html.boot.impl.FnUtils; 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@1184: private final ClassLoader cl; jaroslav@1282: private final WebPresenter presenter; 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@1184: final ClassLoader p = JVMBridge.class.getClassLoader().getParent(); jaroslav@1282: this.presenter = new WebPresenter(); jaroslav@1282: this.cl = FnUtils.newLoader(presenter, presenter, p); 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@1282: FnUtils.currentPresenter(presenter); jaroslav@1174: return Class.forName(name, true, cl); jaroslav@1174: } jaroslav@1174: jaroslav@1282: private final class WebPresenter implements FindResources, Fn.Presenter { jaroslav@1174: @Override jaroslav@1184: public void findResources(String name, Collection results, boolean oneIsEnough) { jaroslav@1174: if (ldrs != null) for (ClassLoader l : ldrs) { jaroslav@1174: URL u = l.getResource(name); jaroslav@1174: if (u != null) { jaroslav@1184: results.add(u); jaroslav@1174: } jaroslav@1041: } jaroslav@1175: } jaroslav@1174: jaroslav@1174: @Override jaroslav@1184: public Fn defineFn(String code, String... names) { jaroslav@1174: StringBuilder sb = new StringBuilder(); jaroslav@1174: sb.append("(function() {"); jaroslav@1183: sb.append(" return 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("})()"); jaroslav@1174: jaroslav@1174: JSObject x = (JSObject) engine.executeScript(sb.toString()); jaroslav@1282: return new JSFn(this, x); jaroslav@1041: } jaroslav@1184: jaroslav@1184: @Override jaroslav@1184: public void displayPage(URL page, Runnable onPageLoad) { jaroslav@1233: throw new UnsupportedOperationException("Not supported yet."); jaroslav@1184: } jaroslav@1227: jaroslav@1227: @Override jaroslav@1227: public void loadScript(Reader code) throws Exception { jaroslav@1233: BufferedReader r = new BufferedReader(code); jaroslav@1233: StringBuilder sb = new StringBuilder(); jaroslav@1233: for (;;) { jaroslav@1233: String l = r.readLine(); jaroslav@1233: if (l == null) { jaroslav@1233: break; jaroslav@1233: } jaroslav@1233: sb.append(l).append('\n'); jaroslav@1233: } jaroslav@1233: engine.executeScript(sb.toString()); jaroslav@1227: } jaroslav@1174: } jaroslav@1174: jaroslav@1174: private static final class JSFn extends Fn { jaroslav@1174: private final JSObject fn; jaroslav@1174: jaroslav@1282: private JSFn(WebPresenter cl, JSObject fn) { jaroslav@1282: super(cl); jaroslav@1174: this.fn = fn; jaroslav@1174: } jaroslav@1282: jaroslav@1174: @Override jaroslav@1181: public Object invoke(Object thiz, Object... args) throws Exception { jaroslav@1179: try { jaroslav@1183: List all = new ArrayList(args.length + 1); jaroslav@1183: all.add(thiz == null ? fn : thiz); jaroslav@1183: all.addAll(Arrays.asList(args)); jaroslav@1183: Object ret = fn.call("call", all.toArray()); // NOI18N jaroslav@1183: return ret == fn ? null : ret; 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: }