http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-script/src/test/java/net/java/html/boot/script/ko4j/DynamicHTTP.java ---------------------------------------------------------------------- diff --git a/boot-script/src/test/java/net/java/html/boot/script/ko4j/DynamicHTTP.java b/boot-script/src/test/java/net/java/html/boot/script/ko4j/DynamicHTTP.java new file mode 100644 index 0000000..a408c3b --- /dev/null +++ b/boot-script/src/test/java/net/java/html/boot/script/ko4j/DynamicHTTP.java @@ -0,0 +1,261 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package net.java.html.boot.script.ko4j; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.glassfish.grizzly.PortRange; +import org.glassfish.grizzly.http.server.HttpHandler; +import org.glassfish.grizzly.http.server.HttpServer; +import org.glassfish.grizzly.http.server.NetworkListener; +import org.glassfish.grizzly.http.server.Request; +import org.glassfish.grizzly.http.server.Response; +import org.glassfish.grizzly.http.server.ServerConfiguration; +import org.glassfish.grizzly.websockets.WebSocket; +import org.glassfish.grizzly.websockets.WebSocketAddOn; +import org.glassfish.grizzly.websockets.WebSocketApplication; +import org.glassfish.grizzly.websockets.WebSocketEngine; + +/** + * + * @author Jaroslav Tulach + */ +final class DynamicHTTP extends HttpHandler { + private static final Logger LOG = Logger.getLogger(DynamicHTTP.class.getName()); + private static int resourcesCount; + private static List<Resource> resources; + private static ServerConfiguration conf; + private static HttpServer server; + + private DynamicHTTP() { + } + + static URI initServer() throws Exception { + server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535)); + final WebSocketAddOn addon = new WebSocketAddOn(); + for (NetworkListener listener : server.getListeners()) { + listener.registerAddOn(addon); + } + resources = new ArrayList<Resource>(); + + conf = server.getServerConfiguration(); + final DynamicHTTP dh = new DynamicHTTP(); + + conf.addHttpHandler(dh, "/"); + + server.start(); + + return pageURL("http", server, "/test.html"); + } + + @Override + public void service(Request request, Response response) throws Exception { + if ("/test.html".equals(request.getRequestURI())) { + response.setContentType("text/html"); + final InputStream is = DynamicHTTP.class.getResourceAsStream("test.html"); + copyStream(is, response.getOutputStream(), null); + return; + } + if ("/dynamic".equals(request.getRequestURI())) { + String mimeType = request.getParameter("mimeType"); + List<String> params = new ArrayList<String>(); + boolean webSocket = false; + for (int i = 0;; i++) { + String p = request.getParameter("param" + i); + if (p == null) { + break; + } + if ("protocol:ws".equals(p)) { + webSocket = true; + continue; + } + params.add(p); + } + final String cnt = request.getParameter("content"); + String mangle = cnt.replace("%20", " ").replace("%0A", "\n"); + ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8")); + URI url; + final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()])); + if (webSocket) { + url = registerWebSocket(res); + } else { + url = registerResource(res); + } + response.getWriter().write(url.toString()); + response.getWriter().write("\n"); + return; + } + + for (Resource r : resources) { + if (r.httpPath.equals(request.getRequestURI())) { + response.setContentType(r.httpType); + r.httpContent.reset(); + String[] params = null; + if (r.parameters.length != 0) { + params = new String[r.parameters.length]; + for (int i = 0; i < r.parameters.length; i++) { + params[i] = request.getParameter(r.parameters[i]); + if (params[i] == null) { + if ("http.method".equals(r.parameters[i])) { + params[i] = request.getMethod().toString(); + } else if ("http.requestBody".equals(r.parameters[i])) { + Reader rdr = request.getReader(); + StringBuilder sb = new StringBuilder(); + for (;;) { + int ch = rdr.read(); + if (ch == -1) { + break; + } + sb.append((char) ch); + } + params[i] = sb.toString(); + } else if (r.parameters[i].startsWith("http.header.")) { + params[i] = request.getHeader(r.parameters[i].substring(12)); + } + } + if (params[i] == null) { + params[i] = "null"; + } + } + } + + copyStream(r.httpContent, response.getOutputStream(), null, params); + } + } + } + + private URI registerWebSocket(Resource r) { + WebSocketEngine.getEngine().register("", r.httpPath, new WS(r)); + return pageURL("ws", server, r.httpPath); + } + + private URI registerResource(Resource r) { + if (!resources.contains(r)) { + resources.add(r); + conf.addHttpHandler(this, r.httpPath); + } + return pageURL("http", server, r.httpPath); + } + + private static URI pageURL(String proto, HttpServer server, final String page) { + NetworkListener listener = server.getListeners().iterator().next(); + int port = listener.getPort(); + try { + return new URI(proto + "://localhost:" + port + page); + } catch (URISyntaxException ex) { + throw new IllegalStateException(ex); + } + } + + static final class Resource { + + final InputStream httpContent; + final String httpType; + final String httpPath; + final String[] parameters; + + Resource(InputStream httpContent, String httpType, String httpPath, + String[] parameters) { + httpContent.mark(Integer.MAX_VALUE); + this.httpContent = httpContent; + this.httpType = httpType; + this.httpPath = httpPath; + this.parameters = parameters; + } + } + + static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException { + for (;;) { + int ch = is.read(); + if (ch == -1) { + break; + } + if (ch == '$' && params.length > 0) { + int cnt = is.read() - '0'; + if (baseURL != null && cnt == 'U' - '0') { + os.write(baseURL.getBytes("UTF-8")); + } else { + if (cnt >= 0 && cnt < params.length) { + os.write(params[cnt].getBytes("UTF-8")); + } else { + os.write('$'); + os.write(cnt + '0'); + } + } + } else { + os.write(ch); + } + } + } + + private static class WS extends WebSocketApplication { + private final Resource r; + + private WS(Resource r) { + this.r = r; + } + + @Override + public void onMessage(WebSocket socket, String text) { + try { + r.httpContent.reset(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + copyStream(r.httpContent, out, null, text); + String s = new String(out.toByteArray(), "UTF-8"); + socket.send(s); + } catch (IOException ex) { + LOG.log(Level.WARNING, "Error processing message " + text, ex); + } + } + } +}
http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-script/src/test/java/net/java/html/boot/script/ko4j/KOCase.java ---------------------------------------------------------------------- diff --git a/boot-script/src/test/java/net/java/html/boot/script/ko4j/KOCase.java b/boot-script/src/test/java/net/java/html/boot/script/ko4j/KOCase.java new file mode 100644 index 0000000..0498ea8 --- /dev/null +++ b/boot-script/src/test/java/net/java/html/boot/script/ko4j/KOCase.java @@ -0,0 +1,140 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package net.java.html.boot.script.ko4j; + +import java.io.Closeable; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.netbeans.html.boot.spi.Fn; +import org.testng.ITest; +import org.testng.SkipException; +import org.testng.annotations.Test; + +/** + * + * @author Jaroslav Tulach + */ +public final class KOCase implements ITest, Runnable { + static final Executor JS = Executors.newSingleThreadExecutor(); + private final Fn.Presenter p; + private final Method m; + private final String skipMsg; + private Object result; + private Object inst; + private int count; + + KOCase(Fn.Presenter p, Method m, String skipMsg) { + this.p = p; + this.m = m; + this.skipMsg = skipMsg; + } + + @Override + public String getTestName() { + return m.getName(); + } + + @Test + public synchronized void executeTest() throws Exception { + if (skipMsg != null) { + throw new SkipException(skipMsg); + } + if (result == null) { + JS.execute(this); + wait(); + } + if (result instanceof Exception) { + throw (Exception)result; + } + if (result instanceof Error) { + throw (Error)result; + } + } + + @Override + public synchronized void run() { + boolean notify = true; + Closeable a = Fn.activate(p); + try { + if (inst == null) { + inst = m.getDeclaringClass().newInstance(); + } + result = m.invoke(inst); + if (result == null) { + result = this; + } + } catch (InvocationTargetException ex) { + Throwable r = ex.getTargetException(); + if (r instanceof InterruptedException) { + if (count++ < 1000) { + notify = false; + try { + Thread.sleep(30); + } catch (InterruptedException ignore) { + // just go on + } + JS.execute(this); + return; + } + } + result = r; + } catch (Exception ex) { + result = ex; + } finally { + if (notify) { + notifyAll(); + } + try { + a.close(); + } catch (IOException ex) { + throw new IllegalStateException(ex); + } + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-script/src/test/java/net/java/html/boot/script/ko4j/KnockoutEnvJSTest.java ---------------------------------------------------------------------- diff --git a/boot-script/src/test/java/net/java/html/boot/script/ko4j/KnockoutEnvJSTest.java b/boot-script/src/test/java/net/java/html/boot/script/ko4j/KnockoutEnvJSTest.java new file mode 100644 index 0000000..8ed88c5 --- /dev/null +++ b/boot-script/src/test/java/net/java/html/boot/script/ko4j/KnockoutEnvJSTest.java @@ -0,0 +1,266 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package net.java.html.boot.script.ko4j; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import net.java.html.BrwsrCtx; +import net.java.html.boot.BrowserBuilder; +import net.java.html.boot.script.Scripts; +import net.java.html.js.JavaScriptBody; +import org.netbeans.html.boot.spi.Fn; +import org.netbeans.html.context.spi.Contexts; +import org.netbeans.html.json.spi.Technology; +import org.netbeans.html.json.spi.Transfer; +import org.netbeans.html.json.tck.KOTest; +import org.netbeans.html.json.tck.KnockoutTCK; +import org.netbeans.html.ko4j.KO4J; +import org.netbeans.html.wstyrus.TyrusContext; +import org.openide.util.lookup.ServiceProvider; +import org.testng.Assert; +import static org.testng.Assert.*; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +@ServiceProvider(service = KnockoutTCK.class) +public final class KnockoutEnvJSTest extends KnockoutTCK { + private static Class<?> browserClass; + private static Fn.Presenter browserContext; + private static URI baseUri; + + public KnockoutEnvJSTest() { + } + + @Factory public static Object[] compatibilityTests() throws Exception { + try { + Class.forName("java.lang.FunctionalInterface"); + } catch (ClassNotFoundException ex) { + // only runs on JDK8 + return new Object[0]; + } + + + Class[] arr = testClasses(); + for (int i = 0; i < arr.length; i++) { + assertEquals( + arr[i].getClassLoader(), + KnockoutEnvJSTest.class.getClassLoader(), + "All classes loaded by the same classloader" + ); + } + + baseUri = DynamicHTTP.initServer(); + + final Fn.Presenter p = Scripts.createPresenter(KOCase.JS); + URL envNashorn = new URL("https://bugs.openjdk.java.net/secure/attachment/11894/env.nashorn.1.2-debug.js"); + InputStream is = envNashorn.openStream(); + p.loadScript(new InputStreamReader(is)); + is.close(); + + final BrowserBuilder bb = BrowserBuilder.newBrowser(p). + loadClass(KnockoutEnvJSTest.class). + loadPage(baseUri.toString()). + invoke("initialized"); + + Executors.newSingleThreadExecutor().submit(new Runnable() { + @Override + public void run() { + bb.showAndWait(); + } + }); + + ClassLoader l = getClassLoader(); + List<Object> res = new ArrayList<Object>(); + for (int i = 0; i < arr.length; i++) { + Class<?> c = Class.forName(arr[i].getName(), true, l); + seekKOTests(c, res); + } + return res.toArray(); + } + + private static void seekKOTests(Class<?> c, List<Object> res) throws SecurityException, ClassNotFoundException { + Class<? extends Annotation> koTest = + c.getClassLoader().loadClass(KOTest.class.getName()). + asSubclass(Annotation.class); + for (Method m : c.getMethods()) { + if (m.getAnnotation(koTest) != null) { + res.add(new KOCase(browserContext, m, skipMsg(m.getName()))); + } + } + } + + private static String skipMsg(String methodName) { + final String ver = System.getProperty("java.runtime.version"); // NOI18N + if ( + ver.startsWith("1.8.0_25") || + ver.startsWith("1.8.0_40") + ) { + return "Broken due to JDK-8047764"; + } + if ( + !ver.startsWith("1.8.0_") + ) { + // 1.8.0_ are and will remain broken + return null; + } + switch (methodName) { + case "paintTheGridOnClick": + case "displayContentOfArrayOfPeople": + case "connectUsingWebSocket": + case "selectWorksOnModels": + case "archetypeArrayModificationVisible": + case "noLongerNeededArrayElementsCanDisappear": + return "Does not work on JDK8, due to JDK-8046013"; + case "modifyRadioValueOnEnum": + return "Does not work on JDK8"; + } + return null; + } + + static synchronized ClassLoader getClassLoader() throws InterruptedException { + while (browserClass == null) { + KnockoutEnvJSTest.class.wait(); + } + return browserClass.getClassLoader(); + } + + public static synchronized void initialized(Class<?> browserCls) throws Exception { + browserClass = browserCls; + browserContext = Fn.activePresenter(); + KnockoutEnvJSTest.class.notifyAll(); + } + + public static void initialized() throws Exception { + Assert.assertSame( + KnockoutEnvJSTest.class.getClassLoader(), + ClassLoader.getSystemClassLoader(), + "No special classloaders" + ); + KnockoutEnvJSTest.initialized(KnockoutEnvJSTest.class); + browserContext = Fn.activePresenter(); + } + + @Override + public BrwsrCtx createContext() { + KO4J fx = new KO4J(browserContext); + TyrusContext tc = new TyrusContext(); + Contexts.Builder cb = Contexts.newBuilder(). + register(Technology.class, fx.knockout(), 10). + register(Transfer.class, tc, 10); + cb.register(Fn.Presenter.class, browserContext, 10); + cb.register(Executor.class, (Executor)browserContext, 10); + BrwsrCtx ctx = cb.build(); + return ctx; + } + + @Override + public Object createJSON(Map<String, Object> values) { + Object json = createJSON(); + for (Map.Entry<String, Object> entry : values.entrySet()) { + setProperty(json, entry.getKey(), entry.getValue()); + } + return json; + } + + @JavaScriptBody(args = {}, body = "return new Object();") + private static native Object createJSON(); + @JavaScriptBody(args = { "json", "key", "value" }, body = "json[key] = value;") + private static native void setProperty(Object json, String key, Object value); + + @Override + @JavaScriptBody(args = { "s", "args" }, body = "\n" + + "var f = new Function(s);\n" + + "return f.apply(null, args);\n" + ) + public native Object executeScript(String script, Object[] arguments); + + private static String findBaseURL() { + return baseUri.toString(); + } + + @Override + public URI prepareURL(String content, String mimeType, String[] parameters) { + try { + final URL baseURL = new URL(findBaseURL()); + StringBuilder sb = new StringBuilder(); + sb.append("/dynamic?mimeType=").append(mimeType); + for (int i = 0; i < parameters.length; i++) { + sb.append("¶m" + i).append("=").append(parameters[i]); + } + String mangle = content.replace("\n", "%0a") + .replace("\"", "\\\"").replace(" ", "%20"); + sb.append("&content=").append(mangle); + + URL query = new URL(baseURL, sb.toString()); + URLConnection c = query.openConnection(); + BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream())); + URI connectTo = new URI(br.readLine()); + return connectTo; + } catch (IOException ex) { + throw new IllegalStateException(ex); + } catch (URISyntaxException ex) { + throw new IllegalStateException(ex); + } + } + + @Override + public boolean canFailWebSocketTest() { + return true; + } +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-script/src/test/resources/net/java/html/boot/script/ko4j/test.html ---------------------------------------------------------------------- diff --git a/boot-script/src/test/resources/net/java/html/boot/script/ko4j/test.html b/boot-script/src/test/resources/net/java/html/boot/script/ko4j/test.html new file mode 100644 index 0000000..af8ad2e --- /dev/null +++ b/boot-script/src/test/resources/net/java/html/boot/script/ko4j/test.html @@ -0,0 +1,56 @@ +<!-- + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + + Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + + Oracle and Java are registered trademarks of Oracle and/or its affiliates. + Other names may be trademarks of their respective owners. + + The contents of this file are subject to the terms of either the GNU + General Public License Version 2 only ("GPL") or the Common + Development and Distribution License("CDDL") (collectively, the + "License"). You may not use this file except in compliance with the + License. You can obtain a copy of the License at + http://www.netbeans.org/cddl-gplv2.html + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + specific language governing permissions and limitations under the + License. When distributing the software, include this License Header + Notice in each file and include the License file at + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + particular file as subject to the "Classpath" exception as provided + by Oracle in the GPL Version 2 section of the License file that + accompanied this code. If applicable, add the following below the + License Header, with the fields enclosed by brackets [] replaced by + your own identifying information: + "Portions Copyrighted [year] [name of copyright owner]" + + Contributor(s): + + The Original Software is NetBeans. The Initial Developer of the Original + Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + + If you wish your version of this file to be governed by only the CDDL + or only the GPL Version 2, indicate your decision by adding + "[Contributor] elects to include this software in this distribution + under the [CDDL or GPL Version 2] license." If you do not indicate a + single choice of license, a recipient has the option to distribute + your version of this file under either the CDDL, the GPL Version 2 or + to extend the choice of license to its licensees as provided above. + However, if you add GPL Version 2 code and therefore, elected the GPL + Version 2 license, then the option applies only if the new code is + made subject to such option by the copyright holder. + +--> +<!DOCTYPE html> +<html> + <head> + <title>Knockout.fx Execution Harness</title> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <meta name="viewport" content="width=device-width"> + </head> + <body> + <h1>Knockout in Env.Execution Harness</h1> + <script></script> + </body> +</html> http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/empty.sigtest ---------------------------------------------------------------------- diff --git a/boot-truffle/empty.sigtest b/boot-truffle/empty.sigtest new file mode 100644 index 0000000..42942c0 --- /dev/null +++ b/boot-truffle/empty.sigtest @@ -0,0 +1,21 @@ +#Signature file v4.1 +#Version 2.0-SNAPSHOT + +CLSS public java.lang.Object +cons public init() +meth protected java.lang.Object clone() throws java.lang.CloneNotSupportedException +meth protected void finalize() throws java.lang.Throwable +meth public boolean equals(java.lang.Object) +meth public final java.lang.Class<?> getClass() +meth public final void notify() +meth public final void notifyAll() +meth public final void wait() throws java.lang.InterruptedException +meth public final void wait(long) throws java.lang.InterruptedException +meth public final void wait(long,int) throws java.lang.InterruptedException +meth public int hashCode() +meth public java.lang.String toString() + +CLSS public final net.java.html.boot.truffle.TrufflePresenters +meth public static org.netbeans.html.boot.spi.Fn$Presenter create(java.util.concurrent.Executor) +supr java.lang.Object + http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/pom.xml ---------------------------------------------------------------------- diff --git a/boot-truffle/pom.xml b/boot-truffle/pom.xml new file mode 100644 index 0000000..912aca0 --- /dev/null +++ b/boot-truffle/pom.xml @@ -0,0 +1,209 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + + Copyright 2013-2016 Oracle and/or its affiliates. All rights reserved. + + Oracle and Java are registered trademarks of Oracle and/or its affiliates. + Other names may be trademarks of their respective owners. + + The contents of this file are subject to the terms of either the GNU + General Public License Version 2 only ("GPL") or the Common + Development and Distribution License("CDDL") (collectively, the + "License"). You may not use this file except in compliance with the + License. You can obtain a copy of the License at + http://www.netbeans.org/cddl-gplv2.html + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + specific language governing permissions and limitations under the + License. When distributing the software, include this License Header + Notice in each file and include the License file at + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + particular file as subject to the "Classpath" exception as provided + by Oracle in the GPL Version 2 section of the License file that + accompanied this code. If applicable, add the following below the + License Header, with the fields enclosed by brackets [] replaced by + your own identifying information: + "Portions Copyrighted [year] [name of copyright owner]" + + Contributor(s): + + The Original Software is NetBeans. The Initial Developer of the Original + Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + + If you wish your version of this file to be governed by only the CDDL + or only the GPL Version 2, indicate your decision by adding + "[Contributor] elects to include this software in this distribution + under the [CDDL or GPL Version 2] license." If you do not indicate a + single choice of license, a recipient has the option to distribute + your version of this file under either the CDDL, the GPL Version 2 or + to extend the choice of license to its licensees as provided above. + However, if you add GPL Version 2 code and therefore, elected the GPL + Version 2 license, then the option applies only if the new code is + made subject to such option by the copyright holder. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.netbeans.html</groupId> + <artifactId>pom</artifactId> + <version>2.0-SNAPSHOT</version> + </parent> + <name>Presenter via Truffle</name> + <artifactId>net.java.html.boot.truffle</artifactId> + <version>2.0-SNAPSHOT</version> + <packaging>bundle</packaging> + <properties> + <netbeans.compile.on.save>NONE</netbeans.compile.on.save> + <publicPackages>net.java.html.boot.truffle</publicPackages> + <trufflejs>${java.home}/language/js/trufflejs.jar</trufflejs> + <skipTests>true</skipTests> + </properties> + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Export-Package>${publicPackages}</Export-Package> + <Bundle-SymbolicName>net.java.html.boot.truffle</Bundle-SymbolicName> + </instructions> + </configuration> + </plugin> + <plugin> + <groupId>org.netbeans.html</groupId> + <artifactId>html4j-maven-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>2.3.2</version> + <configuration> + <source>1.7</source> + <target>1.7</target> + </configuration> + </plugin> + <plugin> + <groupId>org.netbeans.tools</groupId> + <artifactId>sigtest-maven-plugin</artifactId> + <version>1.0</version> + <executions> + <execution> + <goals> + <goal>generate</goal> + <goal>check</goal> + </goals> + </execution> + </executions> + <configuration> + <sigfile>empty.sigtest</sigfile> + </configuration> + </plugin> + </plugins> + </build> + <dependencies> + <dependency> + <groupId>org.netbeans.api</groupId> + <artifactId>org-openide-util-lookup</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.oracle.truffle</groupId> + <artifactId>truffle-api</artifactId> + <version>0.18</version> + </dependency> + <dependency> + <groupId>com.oracle.truffle</groupId> + <artifactId>truffle-dsl-processor</artifactId> + <version>0.18</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.netbeans.html</groupId> + <artifactId>net.java.html.boot</artifactId> + <version>${project.version}</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.testng</groupId> + <artifactId>testng</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>net.java.html.json.tck</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.glassfish.grizzly</groupId> + <artifactId>grizzly-http-server</artifactId> + <version>${grizzly.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.glassfish.grizzly</groupId> + <artifactId>grizzly-websockets-server</artifactId> + <version>${grizzly.version}</version> + <scope>test</scope> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.glassfish.grizzly</groupId> + <artifactId>grizzly-http-servlet</artifactId> + <version>${grizzly.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <scope>test</scope> + <version>3.1.0</version> + </dependency> + <dependency> + <groupId>org.netbeans.html</groupId> + <artifactId>ko4j</artifactId> + <version>${project.version}</version> + <scope>test</scope> + <type>jar</type> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>ko-ws-tyrus</artifactId> + <version>${project.version}</version> + <scope>test</scope> + <type>jar</type> + </dependency> + <dependency> + <groupId>com.dukescript.libraries</groupId> + <artifactId>net.java.html.lib</artifactId> + <version>0.3</version> + <scope>test</scope> + </dependency> + </dependencies> + <profiles> + <profile> + <id>graalvm</id> + <activation> + <file> + <exists>${trufflejs}</exists> + </file> + </activation> + <properties> + <skipTests>false</skipTests> + </properties> + <dependencies> + <dependency> + <groupId>com.oracle.graaljs</groupId> + <artifactId>truffle-js</artifactId> + <version>0.07</version> + <systemPath>${trufflejs}</systemPath> + <scope>system</scope> + </dependency> + </dependencies> + </profile> + </profiles> +</project> http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/src/main/java/net/java/html/boot/truffle/IsArrayNode.java ---------------------------------------------------------------------- diff --git a/boot-truffle/src/main/java/net/java/html/boot/truffle/IsArrayNode.java b/boot-truffle/src/main/java/net/java/html/boot/truffle/IsArrayNode.java new file mode 100644 index 0000000..a4e8913 --- /dev/null +++ b/boot-truffle/src/main/java/net/java/html/boot/truffle/IsArrayNode.java @@ -0,0 +1,68 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package net.java.html.boot.truffle; + +import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.RootNode; + +final class IsArrayNode extends RootNode { + @Child + private Node check; + + IsArrayNode() { + super(TruffleLanguage.class, null, null); + this.check = Message.HAS_SIZE.createNode(); + } + + @Override + public Object execute(VirtualFrame frame) { + final Object[] args = frame.getArguments(); + Object result = ForeignAccess.sendHasSize(check, frame, (TruffleObject) args[0]); + return result; + } +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/src/main/java/net/java/html/boot/truffle/IsNullNode.java ---------------------------------------------------------------------- diff --git a/boot-truffle/src/main/java/net/java/html/boot/truffle/IsNullNode.java b/boot-truffle/src/main/java/net/java/html/boot/truffle/IsNullNode.java new file mode 100644 index 0000000..250ae42 --- /dev/null +++ b/boot-truffle/src/main/java/net/java/html/boot/truffle/IsNullNode.java @@ -0,0 +1,68 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package net.java.html.boot.truffle; + +import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.RootNode; + +final class IsNullNode extends RootNode { + @Child + private Node check; + + IsNullNode() { + super(TruffleLanguage.class, null, null); + this.check = Message.IS_NULL.createNode(); + } + + @Override + public Object execute(VirtualFrame frame) { + final Object[] args = frame.getArguments(); + Object result = ForeignAccess.sendIsNull(check, frame, (TruffleObject) args[0]); + return result; + } +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaArray.java ---------------------------------------------------------------------- diff --git a/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaArray.java b/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaArray.java new file mode 100644 index 0000000..2e7c8a1 --- /dev/null +++ b/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaArray.java @@ -0,0 +1,102 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package net.java.html.boot.truffle; + +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.MessageResolution; +import com.oracle.truffle.api.interop.Resolve; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.Node; +import java.lang.reflect.Array; + +@MessageResolution(receiverType = JavaArray.class, language = TrufflePresenter.JavaLang.class) +final class JavaArray extends JavaValue implements TruffleObject { + final TrufflePresenter.WrapArray wrap; + final Object arr; + + public JavaArray(TrufflePresenter.WrapArray wrap, Object arr) { + this.arr = arr; + this.wrap = wrap; + } + + @Override + public ForeignAccess getForeignAccess() { + return JavaArrayForeign.ACCESS; + } + + @Override + public Object get() { + return arr; + } + + static boolean isInstance(TruffleObject obj) { + return obj instanceof JavaArray; + } + + static boolean isArray(Object obj) { + return obj != null && obj.getClass().getComponentType() != null; + } + + @Resolve(message = "READ") + static abstract class ReadNode extends Node { + protected Object access(JavaArray arr, int index) { + Object obj = Array.get(arr.arr, index); + return toJavaScript(obj, arr.wrap); + } + } + + @Resolve(message = "HAS_SIZE") + static abstract class HasSizeNode extends Node { + protected boolean access(JavaArray arr) { + return true; + } + } + + @Resolve(message = "GET_SIZE") + static abstract class GetSizeNode extends Node { + protected int access(JavaArray arr) { + return Array.getLength(arr.arr); + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaObject.java ---------------------------------------------------------------------- diff --git a/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaObject.java b/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaObject.java new file mode 100644 index 0000000..234f396 --- /dev/null +++ b/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaObject.java @@ -0,0 +1,82 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package net.java.html.boot.truffle; + +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.MessageResolution; +import com.oracle.truffle.api.interop.Resolve; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.Node; + +@MessageResolution(receiverType = JavaObject.class, language = TrufflePresenter.JavaLang.class) +final class JavaObject extends JavaValue implements TruffleObject { + final Object obj; + + JavaObject(Object obj) { + this.obj = obj; + } + + + @Override + public ForeignAccess getForeignAccess() { + return JavaObjectForeign.ACCESS; + } + + public static boolean isInstance(TruffleObject obj) { + return obj instanceof JavaObject; + } + + @Override + public Object get() { + return obj; + } + + @Resolve(message = "HAS_SIZE") + static abstract class NoSizeNode extends Node { + + protected boolean access(JavaObject obj) { + return false; + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaValue.java ---------------------------------------------------------------------- diff --git a/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaValue.java b/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaValue.java new file mode 100644 index 0000000..94bba23 --- /dev/null +++ b/boot-truffle/src/main/java/net/java/html/boot/truffle/JavaValue.java @@ -0,0 +1,91 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package net.java.html.boot.truffle; + +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.java.JavaInterop; + +abstract class JavaValue { + public abstract Object get(); + + static Object toJavaScript(Object conv, TrufflePresenter.WrapArray wrap) { + if (conv instanceof TruffleObject) { + return conv; + } + if (JavaArray.isArray(conv)) { + conv = wrap.copy(new JavaArray(wrap, conv)); + } + if (conv instanceof Character) { + conv = (int) (Character) conv; + } + if (conv == null || conv.getClass().getName().endsWith(".$JsCallbacks$")) { // NOI18N + conv = JavaInterop.asTruffleObject(conv); + } else if (!isJSReady(conv)) { + conv = new JavaObject(conv); + } + return conv; + } + + private static boolean isJSReady(Object obj) { + if (obj == null) { + return true; + } + if (obj instanceof String) { + return true; + } + if (obj instanceof Number) { + return true; + } + if (obj instanceof Character) { + return true; + } + if (obj instanceof Boolean) { + return true; + } + if (obj instanceof TruffleObject) { + return true; + } + return false; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/src/main/java/net/java/html/boot/truffle/TrufflePresenter.java ---------------------------------------------------------------------- diff --git a/boot-truffle/src/main/java/net/java/html/boot/truffle/TrufflePresenter.java b/boot-truffle/src/main/java/net/java/html/boot/truffle/TrufflePresenter.java new file mode 100644 index 0000000..7d75efb --- /dev/null +++ b/boot-truffle/src/main/java/net/java/html/boot/truffle/TrufflePresenter.java @@ -0,0 +1,293 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package net.java.html.boot.truffle; + +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.java.JavaInterop; +import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.api.vm.PolyglotEngine; +import java.io.Closeable; +import java.io.IOException; +import java.io.Reader; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Executor; +import org.netbeans.html.boot.spi.Fn; +import org.netbeans.html.boot.spi.Fn.Presenter; + +/** + * Implementation of {@link Presenter} that delegates to Truffle. + * + * @author Jaroslav Tulach + */ +final class TrufflePresenter implements Fn.KeepAlive, + Presenter, Fn.FromJavaScript, Fn.ToJavaScript, Executor { + + private Eval eval; + private WrapArray copy; + private final Executor exc; + private final CallTarget isNull; + private final CallTarget isArray; + private Apply apply; + private TruffleObject jsNull; + + TrufflePresenter(Executor exc, TruffleObject eval) { + this.exc = exc; + this.eval = eval == null ? null : JavaInterop.asJavaFunction(Eval.class, eval); + this.isNull = Truffle.getRuntime().createCallTarget(new IsNullNode()); + this.isArray = Truffle.getRuntime().createCallTarget(new IsArrayNode()); + } + + @Override + public Fn defineFn(String code, String... names) { + return defineImpl(code, names, null); + } + + @Override + public Fn defineFn(String code, String[] names, boolean[] keepAlive) { + return defineImpl(code, names, keepAlive); + } + + private FnImpl defineImpl(String code, String[] names, boolean[] keepAlive) { + StringBuilder sb = new StringBuilder(); + sb.append("(function() {\n"); + sb.append(" var args = Array.prototype.slice.call(arguments);\n"); + sb.append(" var thiz = args.shift();\n"); + sb.append(" return (function("); + String sep = ""; + for (String n : names) { + sb.append(sep).append(n); + sep = ","; + } + sb.append(") {\n"); + sb.append(code); + sb.append("\n }).apply(thiz, args);\n"); + sb.append("})\n"); + + TruffleObject fn = (TruffleObject) getEval().eval(sb.toString()); + return new FnImpl(this, fn, names.length); + } + + @Override + public void displayPage(URL page, Runnable onPageLoad) { + if (onPageLoad != null) { + onPageLoad.run(); + } + } + + @Override + public void loadScript(Reader code) throws Exception { + Source src = Source.newBuilder(code). + name("unknown.js"). + mimeType("text/javascript"). + build(); + getEval().eval(src.getCode()); + } + + interface Apply { + public Object apply(Object... args); + } + + interface WrapArray { + public Object copy(Object arr); + } + + interface Eval { + public Object eval(String code); + } + + final Object checkArray(Object val) throws Exception { + if (val instanceof TruffleObject) { + final TruffleObject truffleObj = (TruffleObject)val; + boolean hasSize = (boolean) isArray.call(truffleObj); + if (hasSize) { + List<?> list = JavaInterop.asJavaObject(List.class, truffleObj); + Object[] arr = list.toArray(); + for (int i = 0; i < arr.length; i++) { + arr[i] = toJava(arr[i]); + } + return arr; + } + } + return val; + } + + @Override + public Object toJava(Object jsArray) { + if (jsArray instanceof JavaValue) { + jsArray = ((JavaValue) jsArray).get(); + } + if (jsArray instanceof TruffleObject) { + boolean checkNull = (boolean) isNull.call(jsArray); + if (checkNull) { + return null; + } + } + try { + return checkArray(jsArray); + } catch (Exception ex) { + throw new IllegalStateException(ex); + } + } + + @Override + public Object toJavaScript(Object conv) { + return JavaValue.toJavaScript(conv, getWrap()); + } + + @Override + public void execute(final Runnable command) { + if (Fn.activePresenter() == this) { + command.run(); + return; + } + + class Wrap implements Runnable { + + @Override + public void run() { + try (Closeable c = Fn.activate(TrufflePresenter.this)) { + command.run(); + } catch (IOException ex) { + throw new IllegalStateException(ex); + } + } + } + final Runnable wrap = new Wrap(); + if (exc == null) { + wrap.run(); + } else { + exc.execute(wrap); + } + } + + private Eval getEval() { + if (eval == null) { + try { + final PolyglotEngine engine = PolyglotEngine.newBuilder().build(); + TruffleObject fn = (TruffleObject) engine.eval( + Source.newBuilder("eval.bind(this)"). + mimeType("text/javascript"). + name("eval.js").build() + ).get(); + eval = JavaInterop.asJavaFunction(Eval.class, fn); + } catch (RuntimeException ex) { + throw ex; + } catch (Exception ex) { + throw new IllegalStateException(ex); + } + } + return eval; + } + + private WrapArray getWrap() { + if (copy == null) { + TruffleObject fn = (TruffleObject) getEval().eval("(function(arr) {\n" + + " var n = [];\n" + + " for (var i = 0; i < arr.length; i++) {\n" + + " n[i] = arr[i];\n" + + " }\n" + + " return n;\n" + + "}).bind(this)" + ); + copy = JavaInterop.asJavaFunction(WrapArray.class, fn); + } + return copy; + } + + private Apply getApply() { + if (apply == null) { + TruffleObject fn = (TruffleObject) getEval().eval("(function() {\n" + + " var args = Array.prototype.slice.call(arguments);\n" + + " var fn = args.shift();\n" + + " return fn.apply(null, args);\n" + + "}).bind(this)" + ); + apply = JavaInterop.asJavaFunction(Apply.class, fn); + } + return apply; + } + + private TruffleObject jsNull() { + if (jsNull == null) { + jsNull = (TruffleObject) getEval().eval("null"); // NOI18N + } + return jsNull; + } + + private class FnImpl extends Fn { + + private final TruffleObject fn; + + public FnImpl(Presenter presenter, TruffleObject fn, int arity) { + super(presenter); + this.fn = fn; + } + + @Override + public Object invoke(Object thiz, Object... args) throws Exception { + List<Object> all = new ArrayList<>(args.length + 1); + all.add(fn); + all.add(thiz == null ? jsNull() : toJavaScript(thiz)); + for (Object conv : args) { + conv = toJavaScript(conv); + all.add(conv); + } + Object ret = getApply().apply(all.toArray()); + if (ret instanceof JavaValue) { + ret = ((JavaValue)ret).get(); + } + if (ret == fn) { + return null; + } + return toJava(ret); + } + } + + static abstract class JavaLang extends TruffleLanguage<Object> { + } +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/src/main/java/net/java/html/boot/truffle/TrufflePresenters.java ---------------------------------------------------------------------- diff --git a/boot-truffle/src/main/java/net/java/html/boot/truffle/TrufflePresenters.java b/boot-truffle/src/main/java/net/java/html/boot/truffle/TrufflePresenters.java new file mode 100644 index 0000000..47df9d3 --- /dev/null +++ b/boot-truffle/src/main/java/net/java/html/boot/truffle/TrufflePresenters.java @@ -0,0 +1,66 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package net.java.html.boot.truffle; + +import java.util.concurrent.Executor; +import org.netbeans.html.boot.spi.Fn; + + +/** Integration with Truffle and + * <a href="http://www.oracle.com/technetwork/oracle-labs/program-languages/overview/">GraalVM</a>. + * + * @since 1.4 + */ +public final class TrufflePresenters { + private TrufflePresenters() { + } + + /** Creates new instance of Truffle based presenter. + * + * @param executor the executor to run requests in + * @return new instance of the presenter + */ + public static Fn.Presenter create(Executor executor) { + return new TrufflePresenter(executor, null); + } +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/src/main/java/net/java/html/boot/truffle/package.html ---------------------------------------------------------------------- diff --git a/boot-truffle/src/main/java/net/java/html/boot/truffle/package.html b/boot-truffle/src/main/java/net/java/html/boot/truffle/package.html new file mode 100644 index 0000000..321c3e9 --- /dev/null +++ b/boot-truffle/src/main/java/net/java/html/boot/truffle/package.html @@ -0,0 +1,51 @@ +<!-- + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + + Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + + Oracle and Java are registered trademarks of Oracle and/or its affiliates. + Other names may be trademarks of their respective owners. + + The contents of this file are subject to the terms of either the GNU + General Public License Version 2 only ("GPL") or the Common + Development and Distribution License("CDDL") (collectively, the + "License"). You may not use this file except in compliance with the + License. You can obtain a copy of the License at + http://www.netbeans.org/cddl-gplv2.html + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + specific language governing permissions and limitations under the + License. When distributing the software, include this License Header + Notice in each file and include the License file at + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + particular file as subject to the "Classpath" exception as provided + by Oracle in the GPL Version 2 section of the License file that + accompanied this code. If applicable, add the following below the + License Header, with the fields enclosed by brackets [] replaced by + your own identifying information: + "Portions Copyrighted [year] [name of copyright owner]" + + Contributor(s): + + The Original Software is NetBeans. The Initial Developer of the Original + Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + + If you wish your version of this file to be governed by only the CDDL + or only the GPL Version 2, indicate your decision by adding + "[Contributor] elects to include this software in this distribution + under the [CDDL or GPL Version 2] license." If you do not indicate a + single choice of license, a recipient has the option to distribute + your version of this file under either the CDDL, the GPL Version 2 or + to extend the choice of license to its licensees as provided above. + However, if you add GPL Version 2 code and therefore, elected the GPL + Version 2 license, then the option applies only if the new code is + made subject to such option by the copyright holder. + +--> +<body> + <p> + Integration with <a href="http://github.com/graalvm/truffle">Truffle</a> + useful to execute against <b>node.js</b> running on top of + the <a href="http://www.oracle.com/technetwork/oracle-labs/program-languages/overview/">GraalVM</a>. + </p> +</body> http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/src/test/java/net/java/html/boot/truffle/JsArrayTruffleTest.java ---------------------------------------------------------------------- diff --git a/boot-truffle/src/test/java/net/java/html/boot/truffle/JsArrayTruffleTest.java b/boot-truffle/src/test/java/net/java/html/boot/truffle/JsArrayTruffleTest.java new file mode 100644 index 0000000..1b7c4f0 --- /dev/null +++ b/boot-truffle/src/test/java/net/java/html/boot/truffle/JsArrayTruffleTest.java @@ -0,0 +1,140 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package net.java.html.boot.truffle; + +import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.api.vm.PolyglotEngine; +import java.io.Closeable; +import java.io.IOException; +import net.java.html.lib.Array; +import net.java.html.lib.Function; +import org.netbeans.html.boot.spi.Fn; +import org.testng.Assert; +import static org.testng.Assert.assertEquals; +import org.testng.SkipException; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +public class JsArrayTruffleTest { + private Fn.Presenter presenter; + private Closeable close; + + @BeforeMethod + public void initializePresenter() throws Exception { + PolyglotEngine engine = PolyglotEngine.newBuilder().build(); + int fourtyTwo; + try { + fourtyTwo = engine.eval( + Source.newBuilder("6 * 7"). + mimeType("text/javascript"). + name("meaning.js"). + build() + ).as(Number.class).intValue(); + presenter = TrufflePresenters.create(null); + close = Fn.activate(presenter); + } catch (Throwable ex) { + fourtyTwo = 42; + } + assertEquals(fourtyTwo, 42, "Meaning of Graal"); + + } + + @AfterMethod + public void closePresenter() throws IOException { + if (close != null) { + close.close(); + } + } + + + @Test + public void forEachArray() { + if (presenter == null) { + throw new SkipException("No presenter found, not running on GraalVM"); + } + Array<String> array = new Array<>(); + array.push("Hello"); + array.push("World"); + array.push("how"); + array.push("are", "You?"); + + Assert.assertEquals(array.length(), 5, "Five words"); + + final Array<String> lowerCaseArray = new Array<>(); + array.forEach(new Function.A1<String, Void>() { + @Override + public Void call(String p1) { + lowerCaseArray.push(p1.toLowerCase()); + return null; + } + + @Override + public Void call(String p1, Object p2) { + return call(p1); + } + + @Override + public Void call(String p1, Object p2, Object p3) { + return call(p1); + } + + @Override + public Void call(String p1, Object p2, Object p3, Object p4) { + return call(p1); + } + + @Override + public Void call(String p1, Object p2, Object p3, Object p4, Object p5) { + return call(p1); + } + }); + + assertEquals(lowerCaseArray.$get(0), "hello"); + assertEquals(lowerCaseArray.$get(1), "world"); + assertEquals(lowerCaseArray.$get(2), "how"); + assertEquals(lowerCaseArray.$get(3), "are"); + assertEquals(lowerCaseArray.$get(4), "you?"); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot-truffle/src/test/java/net/java/html/boot/truffle/SingleCase.java ---------------------------------------------------------------------- diff --git a/boot-truffle/src/test/java/net/java/html/boot/truffle/SingleCase.java b/boot-truffle/src/test/java/net/java/html/boot/truffle/SingleCase.java new file mode 100644 index 0000000..7bf99b0 --- /dev/null +++ b/boot-truffle/src/test/java/net/java/html/boot/truffle/SingleCase.java @@ -0,0 +1,127 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package net.java.html.boot.truffle; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import org.netbeans.html.boot.spi.Fn; +import org.netbeans.html.boot.impl.FnContext; +import org.testng.IHookCallBack; +import org.testng.IHookable; +import org.testng.ITest; +import org.testng.ITestResult; +import org.testng.annotations.Test; + +/** + * + * @author Jaroslav Tulach + */ +public final class SingleCase implements ITest, IHookable, Runnable { + static final Executor JS = Executors.newSingleThreadExecutor(); + private final Fn.Presenter p; + private final Method m; + private Object result; + private Object inst; + + SingleCase(Fn.Presenter p, Method m) { + this.p = p; + this.m = m; + } + + @Override + public String getTestName() { + return m.getName(); + } + + @Test + public synchronized void executeTest() throws Exception { + if (result == null) { + JS.execute(this); + wait(); + } + if (result instanceof Exception) { + throw (Exception)result; + } + if (result instanceof Error) { + throw (Error)result; + } + } + + @Override + public synchronized void run() { + boolean notify = true; + try { + FnContext.currentPresenter(p); + if (inst == null) { + inst = m.getDeclaringClass().newInstance(); + } + result = m.invoke(inst); + if (result == null) { + result = this; + } + } catch (InvocationTargetException ex) { + Throwable r = ex.getTargetException(); + if (r instanceof InterruptedException) { + notify = false; + JS.execute(this); + return; + } + result = r; + } catch (Exception ex) { + result = ex; + } finally { + if (notify) { + notifyAll(); + } + FnContext.currentPresenter(null); + } + } + + @Override + public void run(IHookCallBack ihcb, ITestResult itr) { + ihcb.runTestMethod(itr); + } + +}
