jaroslav@1170: /** jaroslav@1170: * Back 2 Browser Bytecode Translator jaroslav@1170: * Copyright (C) 2012 Jaroslav Tulach jaroslav@1170: * jaroslav@1170: * This program is free software: you can redistribute it and/or modify jaroslav@1170: * it under the terms of the GNU General Public License as published by jaroslav@1170: * the Free Software Foundation, version 2 of the License. jaroslav@1170: * jaroslav@1170: * This program is distributed in the hope that it will be useful, jaroslav@1170: * but WITHOUT ANY WARRANTY; without even the implied warranty of jaroslav@1170: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the jaroslav@1170: * GNU General Public License for more details. jaroslav@1170: * jaroslav@1170: * You should have received a copy of the GNU General Public License jaroslav@1170: * along with this program. Look for COPYING file in the top folder. jaroslav@1170: * If not, see http://opensource.org/licenses/GPL-2.0. jaroslav@1170: */ jaroslav@1170: package org.apidesign.bck2brwsr.launcher.fximpl; jaroslav@1170: jaroslav@1227: import java.io.Reader; jaroslav@1170: import java.lang.reflect.InvocationTargetException; jaroslav@1170: import java.lang.reflect.Method; jaroslav@1170: import java.net.URL; jaroslav@1174: import java.net.URLClassLoader; jaroslav@1182: import java.util.ArrayList; jaroslav@1182: import java.util.Arrays; jaroslav@1184: import java.util.Collection; jaroslav@1182: import java.util.List; jaroslav@1170: import javax.script.Invocable; jaroslav@1170: import javax.script.ScriptEngine; jaroslav@1170: import javax.script.ScriptEngineManager; jaroslav@1170: import javax.script.ScriptException; jaroslav@1184: import org.apidesign.html.boot.spi.Fn; jaroslav@1184: import org.apidesign.html.boot.impl.FindResources; jaroslav@1184: import org.apidesign.html.boot.impl.FnUtils; jaroslav@1170: import static org.testng.Assert.*; jaroslav@1170: import org.testng.annotations.BeforeClass; jaroslav@1282: import org.testng.annotations.BeforeMethod; jaroslav@1170: import org.testng.annotations.Test; jaroslav@1170: jaroslav@1170: /** jaroslav@1170: * jaroslav@1170: * @author Jaroslav Tulach jaroslav@1170: */ jaroslav@1170: public class JsClassLoaderTest { jaroslav@1170: private static ClassLoader loader; jaroslav@1170: private static Class methodClass; jaroslav@1282: private static Fn.Presenter presenter; jaroslav@1170: jaroslav@1170: public JsClassLoaderTest() { jaroslav@1170: } jaroslav@1170: jaroslav@1170: @BeforeClass jaroslav@1170: public static void setUpClass() throws Exception { jaroslav@1170: ScriptEngineManager sem = new ScriptEngineManager(); jaroslav@1170: final ScriptEngine eng = sem.getEngineByMimeType("text/javascript"); jaroslav@1170: jaroslav@1174: final URL my = JsClassLoaderTest.class.getProtectionDomain().getCodeSource().getLocation(); jaroslav@1170: ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent(); jaroslav@1174: final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent); jaroslav@1184: class Fr implements FindResources, Fn.Presenter { jaroslav@1174: @Override jaroslav@1184: public void findResources(String path, Collection results, boolean oneIsEnough) { jaroslav@1184: URL u = ul.getResource(path); jaroslav@1184: if (u != null) { jaroslav@1184: results.add(u); jaroslav@1184: } jaroslav@1174: } jaroslav@1184: jaroslav@1170: @Override jaroslav@1184: public Fn defineFn(String code, String... names) { jaroslav@1170: StringBuilder sb = new StringBuilder(); jaroslav@1170: sb.append("(function() {"); jaroslav@1182: sb.append("return function("); jaroslav@1170: String sep = ""; jaroslav@1170: for (String n : names) { jaroslav@1170: sb.append(sep); jaroslav@1170: sb.append(n); jaroslav@1170: sep = ", "; jaroslav@1170: } jaroslav@1170: sb.append(") {"); jaroslav@1170: sb.append(code); jaroslav@1170: sb.append("};"); jaroslav@1170: sb.append("})()"); jaroslav@1170: try { jaroslav@1170: final Object val = eng.eval(sb.toString()); jaroslav@1282: return new Fn(this) { jaroslav@1170: @Override jaroslav@1181: public Object invoke(Object thiz, Object... args) throws Exception { jaroslav@1182: List all = new ArrayList(args.length + 1); jaroslav@1182: all.add(thiz == null ? val : thiz); jaroslav@1182: all.addAll(Arrays.asList(args)); jaroslav@1170: Invocable inv = (Invocable)eng; jaroslav@1182: Object ret = inv.invokeMethod(val, "call", all.toArray()); jaroslav@1182: return ret == val ? null : ret; jaroslav@1170: } jaroslav@1170: }; jaroslav@1170: } catch (ScriptException ex) { jaroslav@1170: throw new LinkageError("Can't parse: " + sb, ex); jaroslav@1170: } jaroslav@1170: } jaroslav@1175: jaroslav@1175: @Override jaroslav@1184: public void displayPage(URL page, Runnable onPageLoad) { jaroslav@1175: throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. jaroslav@1175: } jaroslav@1227: jaroslav@1227: @Override jaroslav@1227: public void loadScript(Reader code) throws Exception { jaroslav@1227: throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. jaroslav@1227: } jaroslav@1184: } jaroslav@1170: jaroslav@1282: Fr fr = new Fr(); jaroslav@1282: presenter = fr; jaroslav@1282: loader = FnUtils.newLoader(fr, fr, parent); jaroslav@1170: methodClass = loader.loadClass(JsMethods.class.getName()); jaroslav@1170: } jaroslav@1170: jaroslav@1282: @BeforeMethod public void registerPresenter() { jaroslav@1282: FnUtils.currentPresenter(presenter); jaroslav@1282: } jaroslav@1282: jaroslav@1170: @Test public void noParamMethod() throws Throwable { jaroslav@1170: Method plus = methodClass.getMethod("fortyTwo"); jaroslav@1170: try { jaroslav@1170: final Object val = plus.invoke(null); jaroslav@1170: assertTrue(val instanceof Number, "A number returned " + val); jaroslav@1170: assertEquals(((Number)val).intValue(), 42); jaroslav@1170: } catch (InvocationTargetException ex) { jaroslav@1170: throw ex.getTargetException(); jaroslav@1170: } jaroslav@1170: } jaroslav@1172: jaroslav@1170: @Test public void testExecuteScript() throws Throwable { jaroslav@1170: Method plus = methodClass.getMethod("plus", int.class, int.class); jaroslav@1170: try { jaroslav@1170: assertEquals(plus.invoke(null, 10, 20), 30); jaroslav@1170: } catch (InvocationTargetException ex) { jaroslav@1170: throw ex.getTargetException(); jaroslav@1170: } jaroslav@1170: } jaroslav@1178: jaroslav@1178: @Test public void overloadedMethod() throws Throwable { jaroslav@1178: Method plus = methodClass.getMethod("plus", int.class); jaroslav@1178: try { jaroslav@1178: assertEquals(plus.invoke(null, 10), 10); jaroslav@1178: } catch (InvocationTargetException ex) { jaroslav@1178: throw ex.getTargetException(); jaroslav@1178: } jaroslav@1178: } jaroslav@1181: jaroslav@1181: @Test public void instanceMethod() throws Throwable { jaroslav@1181: Method plus = methodClass.getMethod("plusInst", int.class); jaroslav@1181: Object inst = methodClass.newInstance(); jaroslav@1181: try { jaroslav@1181: assertEquals(plus.invoke(inst, 10), 10); jaroslav@1181: } catch (InvocationTargetException ex) { jaroslav@1181: throw ex.getTargetException(); jaroslav@1181: } jaroslav@1181: } jaroslav@1181: jaroslav@1181: @Test public void staticThis() throws Throwable { jaroslav@1181: Method st = methodClass.getMethod("staticThis"); jaroslav@1181: try { jaroslav@1181: assertNull(st.invoke(null)); jaroslav@1181: } catch (InvocationTargetException ex) { jaroslav@1181: throw ex.getTargetException(); jaroslav@1181: } jaroslav@1181: } jaroslav@1181: jaroslav@1181: @Test public void getThis() throws Throwable { jaroslav@1181: Object th = methodClass.newInstance(); jaroslav@1181: Method st = methodClass.getMethod("getThis"); jaroslav@1181: try { jaroslav@1181: assertEquals(st.invoke(th), th); jaroslav@1181: } catch (InvocationTargetException ex) { jaroslav@1181: throw ex.getTargetException(); jaroslav@1181: } jaroslav@1181: } jaroslav@1181: jaroslav@1170: }