jaroslav@260: /** jaroslav@260: * HTML via Java(tm) Language Bindings jaroslav@260: * Copyright (C) 2013 Jaroslav Tulach jaroslav@260: * jaroslav@260: * This program is free software: you can redistribute it and/or modify jaroslav@260: * it under the terms of the GNU General Public License as published by jaroslav@260: * the Free Software Foundation, version 2 of the License. jaroslav@260: * jaroslav@260: * This program is distributed in the hope that it will be useful, jaroslav@260: * but WITHOUT ANY WARRANTY; without even the implied warranty of jaroslav@260: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the jaroslav@260: * GNU General Public License for more details. apidesign.org jaroslav@260: * designates this particular file as subject to the jaroslav@260: * "Classpath" exception as provided by apidesign.org jaroslav@260: * in the License file that accompanied this code. jaroslav@260: * jaroslav@260: * You should have received a copy of the GNU General Public License jaroslav@260: * along with this program. Look for COPYING file in the top folder. jaroslav@260: * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException jaroslav@260: */ jaroslav@260: package org.apidesign.html.wstyrus; jaroslav@260: jaroslav@260: import java.io.BufferedReader; jaroslav@260: import java.io.IOException; jaroslav@260: import java.io.InputStreamReader; jaroslav@260: import java.lang.annotation.Annotation; jaroslav@260: import java.lang.reflect.Method; jaroslav@260: import java.net.URI; jaroslav@260: import java.net.URISyntaxException; jaroslav@260: import java.net.URL; jaroslav@260: import java.net.URLConnection; jaroslav@260: import java.util.ArrayList; jaroslav@260: import java.util.List; jaroslav@260: import java.util.Map; jaroslav@260: import java.util.concurrent.Executors; jaroslav@260: import net.java.html.BrwsrCtx; jaroslav@260: import net.java.html.boot.BrowserBuilder; jaroslav@260: import net.java.html.js.JavaScriptBody; jaroslav@288: import org.apidesign.html.boot.impl.FnUtils; jaroslav@288: import org.apidesign.html.boot.spi.Fn; jaroslav@260: import org.apidesign.html.context.spi.Contexts; jaroslav@260: import org.apidesign.html.json.spi.Technology; jaroslav@260: import org.apidesign.html.json.spi.Transfer; jaroslav@260: import org.apidesign.html.json.spi.WSTransfer; jaroslav@260: import org.apidesign.html.json.tck.KOTest; jaroslav@260: import org.apidesign.html.json.tck.KnockoutTCK; jaroslav@260: import org.apidesign.html.kofx.FXContext; jaroslav@260: import org.json.JSONException; jaroslav@260: import org.json.JSONObject; jaroslav@260: import org.openide.util.lookup.ServiceProvider; jaroslav@260: import org.testng.annotations.Factory; jaroslav@260: import static org.testng.Assert.*; jaroslav@260: jaroslav@260: /** jaroslav@260: * jaroslav@260: * @author Jaroslav Tulach jaroslav@260: */ jaroslav@260: @ServiceProvider(service = KnockoutTCK.class) jaroslav@260: public final class TyrusKnockoutTest extends KnockoutTCK { jaroslav@260: private static Class browserClass; jaroslav@288: private static Fn.Presenter browserContext; jaroslav@260: jaroslav@260: public TyrusKnockoutTest() { jaroslav@260: } jaroslav@260: jaroslav@260: @Factory public static Object[] compatibilityTests() throws Exception { jaroslav@260: Class[] arr = testClasses(); jaroslav@260: for (int i = 0; i < arr.length; i++) { jaroslav@260: assertEquals( jaroslav@260: arr[i].getClassLoader(), jaroslav@260: TyrusKnockoutTest.class.getClassLoader(), jaroslav@260: "All classes loaded by the same classloader" jaroslav@260: ); jaroslav@260: } jaroslav@260: jaroslav@260: URI uri = TyrusDynamicHTTP.initServer(); jaroslav@260: jaroslav@260: final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(TyrusKnockoutTest.class). jaroslav@260: loadPage(uri.toString()). jaroslav@260: invoke("initialized"); jaroslav@260: jaroslav@260: Executors.newSingleThreadExecutor().submit(new Runnable() { jaroslav@260: @Override jaroslav@260: public void run() { jaroslav@260: bb.showAndWait(); jaroslav@260: } jaroslav@260: }); jaroslav@260: jaroslav@260: ClassLoader l = getClassLoader(); jaroslav@260: List res = new ArrayList(); jaroslav@260: for (int i = 0; i < arr.length; i++) { jaroslav@260: Class c = Class.forName(arr[i].getName(), true, l); jaroslav@260: Class koTest = jaroslav@260: c.getClassLoader().loadClass(KOTest.class.getName()). jaroslav@260: asSubclass(Annotation.class); jaroslav@260: for (Method m : c.getMethods()) { jaroslav@260: if (m.getAnnotation(koTest) != null) { jaroslav@288: res.add(new TyrusFX(browserContext, m)); jaroslav@260: } jaroslav@260: } jaroslav@260: } jaroslav@260: return res.toArray(); jaroslav@260: } jaroslav@260: jaroslav@260: static synchronized ClassLoader getClassLoader() throws InterruptedException { jaroslav@260: while (browserClass == null) { jaroslav@260: TyrusKnockoutTest.class.wait(); jaroslav@260: } jaroslav@260: return browserClass.getClassLoader(); jaroslav@260: } jaroslav@260: jaroslav@260: public static synchronized void initialized(Class browserCls) throws Exception { jaroslav@260: browserClass = browserCls; jaroslav@288: browserContext = FnUtils.currentPresenter(); jaroslav@260: TyrusKnockoutTest.class.notifyAll(); jaroslav@260: } jaroslav@260: jaroslav@260: public static void initialized() throws Exception { jaroslav@260: Class classpathClass = ClassLoader.getSystemClassLoader().loadClass(TyrusKnockoutTest.class.getName()); jaroslav@260: Method m = classpathClass.getMethod("initialized", Class.class); jaroslav@260: m.invoke(null, TyrusKnockoutTest.class); jaroslav@288: browserContext = FnUtils.currentPresenter(); jaroslav@260: } jaroslav@260: jaroslav@260: @Override jaroslav@260: public BrwsrCtx createContext() { jaroslav@288: FXContext fx = new FXContext(browserContext); jaroslav@260: TyrusContext tc = new TyrusContext(); jaroslav@260: Contexts.Builder cb = Contexts.newBuilder(). jaroslav@260: register(Technology.class, fx, 10). jaroslav@260: register(Transfer.class, fx, 10). jaroslav@260: register(WSTransfer.class, tc, 10); jaroslav@260: return cb.build(); jaroslav@260: } jaroslav@260: jaroslav@260: @Override jaroslav@260: public Object createJSON(Map values) { jaroslav@260: JSONObject json = new JSONObject(); jaroslav@260: for (Map.Entry entry : values.entrySet()) { jaroslav@260: try { jaroslav@260: json.put(entry.getKey(), entry.getValue()); jaroslav@260: } catch (JSONException ex) { jaroslav@260: throw new IllegalStateException(ex); jaroslav@260: } jaroslav@260: } jaroslav@260: return json; jaroslav@260: } jaroslav@260: jaroslav@260: @Override jaroslav@260: @JavaScriptBody(args = { "s", "args" }, body = "" jaroslav@260: + "var f = new Function(s); " jaroslav@260: + "return f.apply(null, args);" jaroslav@260: ) jaroslav@260: public native Object executeScript(String script, Object[] arguments); jaroslav@260: jaroslav@260: @JavaScriptBody(args = { }, body = jaroslav@260: "var h;" jaroslav@260: + "if (!!window && !!window.location && !!window.location.href)\n" jaroslav@260: + " h = window.location.href;\n" jaroslav@260: + "else " jaroslav@260: + " h = null;" jaroslav@260: + "return h;\n" jaroslav@260: ) jaroslav@260: private static native String findBaseURL(); jaroslav@260: jaroslav@260: @Override jaroslav@260: public URI prepareURL(String content, String mimeType, String[] parameters) { jaroslav@260: try { jaroslav@260: final URL baseURL = new URL(findBaseURL()); jaroslav@260: StringBuilder sb = new StringBuilder(); jaroslav@260: sb.append("/dynamic?mimeType=").append(mimeType); jaroslav@260: for (int i = 0; i < parameters.length; i++) { jaroslav@260: sb.append("¶m" + i).append("=").append(parameters[i]); jaroslav@260: } jaroslav@260: String mangle = content.replace("\n", "%0a") jaroslav@260: .replace("\"", "\\\"").replace(" ", "%20"); jaroslav@260: sb.append("&content=").append(mangle); jaroslav@260: jaroslav@260: URL query = new URL(baseURL, sb.toString()); jaroslav@260: URLConnection c = query.openConnection(); jaroslav@260: BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream())); jaroslav@260: URI connectTo = new URI(br.readLine()); jaroslav@260: return connectTo; jaroslav@260: } catch (IOException ex) { jaroslav@260: throw new IllegalStateException(ex); jaroslav@260: } catch (URISyntaxException ex) { jaroslav@260: throw new IllegalStateException(ex); jaroslav@260: } jaroslav@260: } jaroslav@260: }