You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by jt...@apache.org on 2017/09/03 12:48:51 UTC
[18/24] incubator-netbeans-html4j git commit: [INFRA-15006] Initial
donation of HTML/Java NetBeans API. Equivalent to the content of
html4j-donation-review.zip donated as part of ApacheNetBeansDonation1.zip
with SHA256 being 7f2ca0f61953a190613c9a0fbcc1b
http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/main/java/org/netbeans/html/boot/spi/Fn.java
----------------------------------------------------------------------
diff --git a/boot/src/main/java/org/netbeans/html/boot/spi/Fn.java b/boot/src/main/java/org/netbeans/html/boot/spi/Fn.java
new file mode 100644
index 0000000..c6deffb
--- /dev/null
+++ b/boot/src/main/java/org/netbeans/html/boot/spi/Fn.java
@@ -0,0 +1,388 @@
+/**
+ * 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 org.netbeans.html.boot.spi;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import net.java.html.js.JavaScriptBody;
+import org.netbeans.html.boot.impl.FnContext;
+
+/** Represents single JavaScript function that can be invoked.
+ * Created via {@link Presenter#defineFn(java.lang.String, java.lang.String...)}.
+ *
+ * @author Jaroslav Tulach
+ */
+public abstract class Fn {
+ private final Presenter presenter;
+
+ /**
+ * @deprecated Ineffective as of 0.6.
+ * Provide a presenter via {@link #Fn(org.netbeans.html.boot.spi.Fn.Presenter)}
+ * constructor
+ */
+ @Deprecated
+ protected Fn() {
+ this(null);
+ }
+
+ /** Creates new function object and associates it with given presenter.
+ *
+ * @param presenter the browser presenter associated with this function
+ * @since 0.6
+ */
+ protected Fn(Presenter presenter) {
+ this.presenter = presenter;
+ }
+
+ /** True, if currently active presenter is the same as presenter this
+ * function has been created for via {@link #Fn(org.netbeans.html.boot.spi.Fn.Presenter)}.
+ *
+ * @return true, if proper presenter is used
+ */
+ public final boolean isValid() {
+ return presenter != null && FnContext.currentPresenter(false) == presenter;
+ }
+
+ /** Helper method to check if the provided instance is valid function.
+ * Checks if the parameter is non-null and if so, does {@link #isValid()}
+ * check.
+ *
+ * @param fnOrNull function or <code>null</code>
+ * @return true if the parameter is non-null and valid
+ * @since 0.7
+ */
+ public static boolean isValid(Fn fnOrNull) {
+ return fnOrNull != null && fnOrNull.isValid();
+ }
+
+ /** Helper method to find current presenter and ask it to define new
+ * function by calling {@link Presenter#defineFn(java.lang.String, java.lang.String...)}.
+ *
+ * @param caller the class who wishes to define the function
+ * @param code the body of the function (can reference <code>this</code> and <code>names</code> variables)
+ * @param names names of individual parameters
+ * @return the function object that can be {@link Fn#invoke(java.lang.Object, java.lang.Object...) invoked}
+ * - can return <code>null</code> if there is {@link #activePresenter() no presenter}
+ * @since 0.7
+ */
+ public static Fn define(Class<?> caller, String code, String... names) {
+ return define(caller, false, code, names);
+ }
+
+ /** Helper method to find current presenter and ask it to define new
+ * function.
+ *
+ * @param caller the class who wishes to define the function
+ * @param keepParametersAlive whether Java parameters should survive in JavaScript
+ * after the method invocation is over
+ * @param code the body of the function (can reference <code>this</code> and <code>names</code> variables)
+ * @param names names of individual parameters
+ * @return the function object that can be {@link Fn#invoke(java.lang.Object, java.lang.Object...) invoked}
+ * - can return <code>null</code> if there is {@link #activePresenter() no presenter}
+ * @since 1.1
+ */
+ public static Fn define(Class<?> caller, boolean keepParametersAlive, String code, String... names) {
+ final Presenter p = FnContext.currentPresenter(false);
+ if (p == null) {
+ return null;
+ }
+ if (p instanceof KeepAlive) {
+ boolean[] arr;
+ if (!keepParametersAlive && names.length > 0) {
+ arr = new boolean[names.length];
+ for (int i = 0; i < arr.length; i++) {
+ arr[i] = false;
+ }
+ } else {
+ arr = null;
+ }
+ return ((KeepAlive)p).defineFn(code, names, arr);
+ }
+ return p.defineFn(code, names);
+ }
+
+ private static final Map<String,Set<Presenter>> LOADED = new HashMap<String, Set<Presenter>>();
+
+ /** Wraps function to ensure that the script represented by <code>resource</code>
+ * gets loaded into the browser environment before the function <code>fn</code>
+ * is executed.
+ *
+ * @param fn original function to call (if <code>null</code> returns <code>null</code>)
+ * @param caller the class who wishes to define/call the function
+ * @param resource resources (accessible via {@link ClassLoader#getResource(java.lang.String)})
+ * with a <em>JavaScript</em> that is supposed to loaded into the browser
+ * environment
+ * @return function that ensures the script is loaded and then delegates
+ * to <code>fn</code>. Returns <code>null</code> if the input <code>fn</code> is null
+ * @since 0.7
+ */
+ public static Fn preload(final Fn fn, final Class<?> caller, final String resource) {
+ if (fn == null) {
+ return null;
+ }
+ return new Fn(fn.presenter()) {
+ @Override
+ public Object invoke(Object thiz, Object... args) throws Exception {
+ loadResource();
+ return fn.invoke(thiz, args);
+ }
+
+ @Override
+ public void invokeLater(Object thiz, Object... args) throws Exception {
+ loadResource();
+ fn.invokeLater(thiz, args);
+ }
+
+ private void loadResource() throws Exception {
+ Presenter p = presenter();
+ if (p == null) {
+ p = FnContext.currentPresenter(false);
+ }
+ if (p != null) {
+ Set<Presenter> there = LOADED.get(resource);
+ if (there == null) {
+ there = new HashSet<Presenter>();
+ LOADED.put(resource, there);
+ }
+ if (there.add(p)) {
+ final ClassLoader l = caller.getClassLoader();
+ InputStream is = l.getResourceAsStream(resource);
+ if (is == null && resource.startsWith("/")) {
+ is = l.getResourceAsStream(resource.substring(1));
+ }
+ if (is == null) {
+ throw new IOException("Cannot find " + resource + " in " + l);
+ }
+ try {
+ InputStreamReader r = new InputStreamReader(is, "UTF-8");
+ p.loadScript(r);
+ } finally {
+ is.close();
+ }
+ }
+ }
+ }
+ };
+ }
+
+
+ /** The currently active presenter.
+ *
+ * @return the currently active presenter or <code>null</code>
+ * @since 0.7
+ */
+ public static Presenter activePresenter() {
+ return FnContext.currentPresenter(false);
+ }
+
+ /** Activates given presenter. Used to associate the native
+ * JavaScript code specified by
+ * {@link JavaScriptBody} annotation with certain presenter:
+ * <pre>
+ * try ({@link Closeable} c = Fn.activate(presenter)) {
+ * doCallsInPresenterContext();
+ * }
+ * </pre>
+ *
+ * @param p the presenter that should be active until closable is closed
+ * @return the closable to close
+ * @since 0.7
+ */
+ public static Closeable activate(Presenter p) {
+ return FnContext.activate(p);
+ }
+
+ /** Invokes the defined function with specified <code>this</code> and
+ * appropriate arguments.
+ *
+ * @param thiz the meaning of <code>this</code> inside of the JavaScript
+ * function - can be <code>null</code>
+ * @param args arguments for the function
+ * @return return value from the function
+ * @throws Exception if something goes wrong, as exception may be thrown
+ */
+ public abstract Object invoke(Object thiz, Object... args) throws Exception;
+
+ /** Invokes the defined function with specified <code>this</code> and
+ * appropriate arguments asynchronously. The invocation may be
+ * happen <em>"later"</em>.
+ *
+ * @param thiz the meaning of <code>this</code> inside of the JavaScript
+ * function - can be <code>null</code>
+ * @param args arguments for the function
+ * @throws Exception if something goes wrong, as exception may be thrown
+ * @since 0.7.6
+ */
+ public void invokeLater(Object thiz, Object... args) throws Exception {
+ invoke(thiz, args);
+ }
+
+ /** Provides the function implementation access to the presenter provided
+ * in {@link #Fn(org.netbeans.html.boot.spi.Fn.Presenter) the constructor}.
+ *
+ * @return presenter passed in the constructor (may be, but should not be <code>null</code>)
+ * @since 0.7
+ */
+ protected final Presenter presenter() {
+ return presenter;
+ }
+
+ /** The representation of a <em>presenter</em> - usually a browser window.
+ * Should be provided by a library included in the application and registered
+ * in <code>META-INF/services</code>, for example with
+ * <code>@ServiceProvider(service = Fn.Presenter.class)</code> annotation.
+ * <p>
+ * Since 0.7 a presenter may implement {@link Executor} interface, in case
+ * it supports single threaded execution environment. The executor's
+ * {@link Executor#execute(java.lang.Runnable)} method is then supposed
+ * to invoke the runnable immediately (in case we are on the right thread
+ * already) or return and asynchronously invoke the runnable later on the
+ * right thread (if we are on wrong thread).
+ */
+ public interface Presenter {
+ /** Creates new function with given parameter names and provided body.
+ *
+ * @param code the body of the function. Can refer to variables named
+ * as <code>names</code>
+ * @param names names of parameters of the function - these will be
+ * available when the <code>code</code> body executes
+ *
+ * @return function that can be later invoked
+ */
+ public Fn defineFn(String code, String... names);
+
+ /** Opens the browser, loads provided page and when the
+ * page is ready, it calls back to the provider runnable.
+ *
+ * @param page the URL for the page to display
+ * @param onPageLoad callback when the page is ready
+ */
+ public void displayPage(URL page, Runnable onPageLoad);
+
+ /** Loads a script into the browser JavaScript interpreter and
+ * executes it.
+ * @param code the script to execute
+ * @throws Exception if something goes wrong, throw an exception
+ */
+ public void loadScript(Reader code) throws Exception;
+ }
+
+ /** Additional interface to be implemented by {@link Presenter}s that
+ * wish to control what objects are passed into the JavaScript virtual
+ * machine.
+ * <p>
+ * If a JavaScript engine makes callback to Java method that returns
+ * a value, the {@link #toJavaScript(java.lang.Object)} method is
+ * consulted to convert the Java value to something reasonable inside
+ * JavaScript VM.
+ * <p>
+ * <em>Note:</em> The implementation based on <em>JavaFX</em> <code>WebView</code>
+ * uses this interface to convert Java arrays to JavaScript ones.
+ *
+ * @see Presenter
+ * @since 0.7
+ */
+ public interface ToJavaScript {
+ /** Convert a Java return value into some object suitable for
+ * JavaScript virtual machine.
+ *
+ * @param toReturn the Java object to be returned
+ * @return the replacement value to return instead
+ */
+ public Object toJavaScript(Object toReturn);
+ }
+
+ /** Additional interface to be implemented by {@link Presenter}s that
+ * need to convert JavaScript object (usually array) to Java object
+ * when calling back from JavaScript to Java.
+ * <p>
+ * <em>Note:</em> The implementation based on <em>JavaFX</em>
+ * <code>WebView</code> uses this interface to convert JavaScript arrays to
+ * Java ones.
+ *
+ * @since 0.7
+ */
+ public interface FromJavaScript {
+ /** Convert a JavaScript object into suitable Java representation
+ * before a Java method is called with this object as an argument.
+ *
+ * @param js the JavaScript object
+ * @return replacement object for
+ */
+ public Object toJava(Object js);
+ }
+
+ /** Additional interface to {@link Presenter} to control more precisely
+ * garbage collection behavior of individual parameters. See
+ * {@link JavaScriptBody#keepAlive()} attribute for description of the
+ * actual behavior of the interface.
+ *
+ * @since 1.1
+ */
+ public interface KeepAlive {
+ /** Creates new function with given parameter names and provided body.
+ *
+ * @param code the body of the function. Can refer to variables named
+ * as <code>names</code>
+ * @param names names of parameters of the function - these will be
+ * available when the <code>code</code> body executes
+ * @param keepAlive array of booleans describing for each parameter
+ * whether it should be kept alive or not. Length of the array
+ * must be the same as length of <code>names</code> array. The
+ * array may be <code>null</code> to signal that all parameters
+ * should be <em>kept alive</em>.
+ *
+ * @return function that can be later invoked
+ */
+ public Fn defineFn(String code, String[] names, boolean[] keepAlive);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/main/java/org/netbeans/html/boot/spi/package.html
----------------------------------------------------------------------
diff --git a/boot/src/main/java/org/netbeans/html/boot/spi/package.html b/boot/src/main/java/org/netbeans/html/boot/spi/package.html
new file mode 100644
index 0000000..d4ef66e
--- /dev/null
+++ b/boot/src/main/java/org/netbeans/html/boot/spi/package.html
@@ -0,0 +1,54 @@
+<!--
+
+ 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>
+ <body>
+ <div>Interfaces for integrators of various execution environments.</div>
+ Not really interesting for clients. The clients should rather use
+ {@link net.java.html.boot.BrowserBuilder} to launch their applications,
+ or (if they need to do some JavaScript calls themselves) look at
+ {@link net.java.html.js.JavaScriptBody} annotation and its usage.
+ </body>
+</html>
http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/main/resources/net/java/html/boot/html4j.txt
----------------------------------------------------------------------
diff --git a/boot/src/main/resources/net/java/html/boot/html4j.txt b/boot/src/main/resources/net/java/html/boot/html4j.txt
new file mode 100644
index 0000000..0552164
--- /dev/null
+++ b/boot/src/main/resources/net/java/html/boot/html4j.txt
@@ -0,0 +1,43 @@
+====
+ 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.
+====
+
http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/test/java/net/java/html/boot/BrowserBuilderTest.java
----------------------------------------------------------------------
diff --git a/boot/src/test/java/net/java/html/boot/BrowserBuilderTest.java b/boot/src/test/java/net/java/html/boot/BrowserBuilderTest.java
new file mode 100644
index 0000000..c4644fa
--- /dev/null
+++ b/boot/src/test/java/net/java/html/boot/BrowserBuilderTest.java
@@ -0,0 +1,134 @@
+/**
+ * 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;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Locale;
+import static org.testng.Assert.*;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public class BrowserBuilderTest {
+ private File dir;
+ private File index;
+
+ public BrowserBuilderTest() {
+ }
+
+ @BeforeMethod public void prepareFiles() throws IOException {
+ dir = File.createTempFile("test", ".dir");
+ dir.delete();
+ assertTrue(dir.mkdirs(), "Dir successfully created: " + dir);
+
+ index = new File(dir, "index.html");
+ index.createNewFile();
+
+ System.setProperty("browser.rootdir", dir.getPath());
+ }
+
+ @AfterMethod public void clearFiles() throws IOException {
+ Files.walkFileTree(dir.toPath(), new FileVisitor<Path>() {
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ Files.delete(file);
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+ Files.delete(dir);
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ }
+
+
+ @Test public void findsZhCN() throws IOException {
+ File zh = new File(dir, "index_zh.html"); zh.createNewFile();
+ File zhCN = new File(dir, "index_zh_CN.html"); zhCN.createNewFile();
+
+ IOException[] mal = { null };
+ URL url = BrowserBuilder.findLocalizedResourceURL("index.html", Locale.SIMPLIFIED_CHINESE, mal, BrowserBuilder.class);
+
+ assertEquals(url, zhCN.toURI().toURL(), "Found both suffixes");
+ }
+
+ @Test public void findsZh() throws IOException {
+ File zh = new File(dir, "index_zh.html"); zh.createNewFile();
+
+ IOException[] mal = { null };
+ URL url = BrowserBuilder.findLocalizedResourceURL("index.html", Locale.SIMPLIFIED_CHINESE, mal, BrowserBuilder.class);
+
+ assertEquals(url, zh.toURI().toURL(), "Found one suffix");
+ }
+
+ @Test public void findsIndex() throws IOException {
+ IOException[] mal = { null };
+ URL url = BrowserBuilder.findLocalizedResourceURL("index.html", Locale.SIMPLIFIED_CHINESE, mal, BrowserBuilder.class);
+
+ assertEquals(url, index.toURI().toURL(), "Found root file");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/test/java/org/netbeans/html/boot/impl/Arithm.java
----------------------------------------------------------------------
diff --git a/boot/src/test/java/org/netbeans/html/boot/impl/Arithm.java b/boot/src/test/java/org/netbeans/html/boot/impl/Arithm.java
new file mode 100644
index 0000000..c4a3cd3
--- /dev/null
+++ b/boot/src/test/java/org/netbeans/html/boot/impl/Arithm.java
@@ -0,0 +1,53 @@
+/**
+ * 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 org.netbeans.html.boot.impl;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public class Arithm {
+ public int sumTwo(int a, int b) {
+ return a + b;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/test/java/org/netbeans/html/boot/impl/Compile.java
----------------------------------------------------------------------
diff --git a/boot/src/test/java/org/netbeans/html/boot/impl/Compile.java b/boot/src/test/java/org/netbeans/html/boot/impl/Compile.java
new file mode 100644
index 0000000..6862e6a
--- /dev/null
+++ b/boot/src/test/java/org/netbeans/html/boot/impl/Compile.java
@@ -0,0 +1,307 @@
+/**
+ * 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 org.netbeans.html.boot.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.tools.Diagnostic;
+import javax.tools.DiagnosticListener;
+import javax.tools.FileObject;
+import javax.tools.ForwardingJavaFileManager;
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.fail;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+final class Compile implements DiagnosticListener<JavaFileObject> {
+ private final List<Diagnostic<? extends JavaFileObject>> errors =
+ new ArrayList<Diagnostic<? extends JavaFileObject>>();
+ private final Map<String, byte[]> classes;
+ private final String pkg;
+ private final String cls;
+ private final String html;
+ private final String sourceLevel;
+
+ private Compile(String html, String code, String sl) throws IOException {
+ this.pkg = findPkg(code);
+ this.cls = findCls(code);
+ this.html = html;
+ this.sourceLevel = sl;
+ classes = compile(html, code);
+ }
+
+ /** Performs compilation of given HTML page and associated Java code
+ */
+ public static Compile create(String html, String code) throws IOException {
+ return create(html, code, "1.7");
+ }
+ static Compile create(String html, String code, String sourceLevel) throws IOException {
+ return new Compile(html, code, sourceLevel);
+ }
+
+ /** Checks for given class among compiled resources */
+ public byte[] get(String res) {
+ return classes.get(res);
+ }
+
+ /** Obtains errors created during compilation.
+ */
+ public List<Diagnostic<? extends JavaFileObject>> getErrors() {
+ return getDiagnostics(Diagnostic.Kind.ERROR);
+ }
+ public List<Diagnostic<? extends JavaFileObject>> getDiagnostics(Diagnostic.Kind kind) {
+ List<Diagnostic<? extends JavaFileObject>> err;
+ err = new ArrayList<Diagnostic<? extends JavaFileObject>>();
+ for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
+ if (diagnostic.getKind() == kind) {
+ err.add(diagnostic);
+ }
+ }
+ return err;
+ }
+
+ private Map<String, byte[]> compile(final String html, final String code) throws IOException {
+ StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
+
+ final Map<String, ByteArrayOutputStream> class2BAOS;
+ class2BAOS = new HashMap<String, ByteArrayOutputStream>();
+
+ JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ return code;
+ }
+ };
+ final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ return html;
+ }
+
+ @Override
+ public InputStream openInputStream() throws IOException {
+ return new ByteArrayInputStream(html.getBytes());
+ }
+ };
+
+ final URI scratch;
+ try {
+ scratch = new URI("mem://mem3");
+ } catch (URISyntaxException ex) {
+ throw new IOException(ex);
+ }
+
+ JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
+ @Override
+ public FileObject getFileForOutput(JavaFileManager.Location location, String packageName, String relativeName, FileObject sibling) throws IOException {
+ try {
+ return new VirtFO(new URI("mem://resource/" + relativeName), Kind.OTHER, relativeName);
+ } catch (URISyntaxException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+
+
+ @Override
+ public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
+ if (kind == Kind.CLASS) {
+ final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+
+ class2BAOS.put(className.replace('.', '/') + ".class", buffer);
+ return new SimpleJavaFileObject(sibling.toUri(), kind) {
+ @Override
+ public OutputStream openOutputStream() throws IOException {
+ return buffer;
+ }
+ };
+ }
+
+ if (kind == Kind.SOURCE) {
+ final String n = className.replace('.', '/') + ".java";
+ final URI un;
+ try {
+ un = new URI("mem://" + n);
+ } catch (URISyntaxException ex) {
+ throw new IOException(ex);
+ }
+ return new VirtFO(un/*sibling.toUri()*/, kind, n);
+ }
+
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
+ if (location == StandardLocation.SOURCE_PATH) {
+ if (packageName.equals(pkg)) {
+ return htmlFile;
+ }
+ if (packageName.isEmpty() && relativeName.startsWith(pkg.replace('.', '/'))) {
+ return htmlFile;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public boolean isSameFile(FileObject a, FileObject b) {
+ if (a instanceof VirtFO && b instanceof VirtFO) {
+ return ((VirtFO)a).getName().equals(((VirtFO)b).getName());
+ }
+
+ return super.isSameFile(a, b);
+ }
+
+ class VirtFO extends SimpleJavaFileObject {
+
+ private final String n;
+
+ public VirtFO(URI uri, Kind kind, String n) {
+ super(uri, kind);
+ this.n = n;
+ }
+ private final ByteArrayOutputStream data = new ByteArrayOutputStream();
+
+ @Override
+ public OutputStream openOutputStream() throws IOException {
+ return data;
+ }
+
+ @Override
+ public String getName() {
+ return n;
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ data.close();
+ return new String(data.toByteArray());
+ }
+ }
+ };
+
+ ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", sourceLevel, "-target", "1.7"), null, Arrays.asList(file)).call();
+
+ Map<String, byte[]> result = new HashMap<String, byte[]>();
+
+ for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
+ result.put(e.getKey(), e.getValue().toByteArray());
+ }
+
+ return result;
+ }
+
+
+ @Override
+ public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+ errors.add(diagnostic);
+ }
+ private static String findPkg(String java) throws IOException {
+ Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
+ Matcher m = p.matcher(java);
+ if (!m.find()) {
+ throw new IOException("Can't find package declaration in the java file");
+ }
+ String pkg = m.group(1);
+ return pkg;
+ }
+ private static String findCls(String java) throws IOException {
+ Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
+ Matcher m = p.matcher(java);
+ if (!m.find()) {
+ throw new IOException("Can't find package declaration in the java file");
+ }
+ String cls = m.group(1);
+ return cls;
+ }
+
+ String getHtml() {
+ String fqn = "'" + pkg + '.' + cls + "'";
+ return html.replace("'${fqn}'", fqn);
+ }
+ void assertErrors() {
+ assertFalse(getErrors().isEmpty(), "There are supposed to be some errors");
+ }
+
+ void assertError(String expMsg) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Can't find ").append(expMsg).append(" among:");
+ for (Diagnostic<? extends JavaFileObject> e : errors) {
+ String msg = e.getMessage(Locale.US);
+ if (msg.contains(expMsg)) {
+ return;
+ }
+ sb.append("\n");
+ sb.append(msg);
+ }
+ fail(sb.toString());
+ }
+
+ void assertNoErrors() {
+ assertTrue(getErrors().isEmpty(), "No errors expected: " + getErrors());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/test/java/org/netbeans/html/boot/impl/CountFnCreationTest.java
----------------------------------------------------------------------
diff --git a/boot/src/test/java/org/netbeans/html/boot/impl/CountFnCreationTest.java b/boot/src/test/java/org/netbeans/html/boot/impl/CountFnCreationTest.java
new file mode 100644
index 0000000..8e3f0e2
--- /dev/null
+++ b/boot/src/test/java/org/netbeans/html/boot/impl/CountFnCreationTest.java
@@ -0,0 +1,123 @@
+/**
+ * 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 org.netbeans.html.boot.impl;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.Reader;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.Collection;
+import java.util.Enumeration;
+import net.java.html.js.JavaScriptBody;
+import net.java.html.js.JavaScriptResource;
+import org.netbeans.html.boot.spi.Fn;
+import static org.testng.Assert.assertEquals;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+@JavaScriptResource("empty.js")
+public class CountFnCreationTest implements Fn.Presenter {
+ private int cnt;
+
+ @JavaScriptBody(args = {}, body = "return;")
+ public static native void body();
+
+ @Test public void countManyTimes() throws Exception {
+ class Res implements FindResources {
+ @Override
+ public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough) {
+ try {
+ ClassLoader l = CountFnCreationTest.class.getClassLoader();
+ Enumeration<URL> en = l.getResources(path);
+ while (en.hasMoreElements()) {
+ results.add(en.nextElement());
+ }
+ } catch (IOException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+ }
+ ClassLoader l = FnUtils.newLoader(new Res(), this, CountFnCreationTest.class.getClassLoader().getParent());
+ Method m = l.loadClass(CountFnCreationTest.class.getName()).getMethod("body");
+ Closeable c = Fn.activate(this);
+ try {
+ assertEquals(cnt, 0, "No functions yet");
+ m.invoke(null);
+ assertEquals(cnt, 1, "One function defined");
+ m.invoke(null);
+ assertEquals(cnt, 1, "Still one function");
+ } finally {
+ c.close();
+ }
+ }
+
+ @Override
+ public Fn defineFn(String code, String... names) {
+ cnt++;
+ return new MyFn(this);
+ }
+
+ @Override
+ public void displayPage(URL page, Runnable onPageLoad) {
+ }
+
+ @Override
+ public void loadScript(Reader code) throws Exception {
+ }
+
+ private static final class MyFn extends Fn {
+
+ public MyFn(Presenter presenter) {
+ super(presenter);
+ }
+
+ @Override
+ public java.lang.Object invoke(java.lang.Object thiz, java.lang.Object... args) throws Exception {
+ return null;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/test/java/org/netbeans/html/boot/impl/FnTest.java
----------------------------------------------------------------------
diff --git a/boot/src/test/java/org/netbeans/html/boot/impl/FnTest.java b/boot/src/test/java/org/netbeans/html/boot/impl/FnTest.java
new file mode 100644
index 0000000..d7c55ab
--- /dev/null
+++ b/boot/src/test/java/org/netbeans/html/boot/impl/FnTest.java
@@ -0,0 +1,186 @@
+/**
+ * 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 org.netbeans.html.boot.impl;
+
+import java.io.Closeable;
+import java.io.Flushable;
+import java.io.IOException;
+import java.io.Reader;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import javax.script.Invocable;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import org.netbeans.html.boot.spi.Fn;
+import static org.testng.Assert.assertEquals;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public class FnTest extends JsClassLoaderBase {
+ private static Fn.Presenter presenter;
+
+ public FnTest() {
+ }
+
+ @BeforeClass
+ public static void createClassLoader() throws Exception {
+ ScriptEngineManager sem = new ScriptEngineManager();
+ final ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
+
+ final URL my = FnTest.class.getProtectionDomain().getCodeSource().getLocation();
+ ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
+ final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
+
+ class Impl implements FindResources, Fn.Presenter {
+ @Override
+ public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough) {
+ URL u = ul.findResource(path);
+ if (u != null) {
+ results.add(u);
+ }
+ }
+
+ @Override
+ public Fn defineFn(String code, String... names) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("(function() {");
+ sb.append("return function(");
+ String sep = "";
+ for (String n : names) {
+ sb.append(sep);
+ sb.append(n);
+ sep = ", ";
+ }
+ sb.append(") {");
+ sb.append(code);
+ sb.append("};");
+ sb.append("})()");
+ try {
+ final java.lang.Object val = eng.eval(sb.toString());
+ return new Fn(this) {
+ @Override
+ public java.lang.Object invoke(java.lang.Object thiz, java.lang.Object... args) throws Exception {
+ List<java.lang.Object> all = new ArrayList<java.lang.Object>(args.length + 1);
+ all.add(thiz == null ? val : thiz);
+ all.addAll(Arrays.asList(args));
+ Invocable inv = (Invocable)eng;
+ try {
+ java.lang.Object ret = inv.invokeMethod(val, "call", all.toArray());
+ return val.equals(ret) ? null : ret;
+ } catch (ScriptException ex) {
+ throw ex;
+ }
+ }
+ };
+ } catch (ScriptException ex) {
+ throw new LinkageError("Can't parse: " + sb, ex);
+ }
+ }
+
+ @Override
+ public void displayPage(URL resource, Runnable r) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void loadScript(Reader code) throws Exception {
+ eng.eval(code);
+ }
+ }
+ Impl impl = new Impl();
+ ClassLoader loader = FnUtils.newLoader(impl, impl, parent);
+ presenter = impl;
+
+ Closeable close = FnContext.activate(impl);
+ methodClass = loader.loadClass(JsMethods.class.getName());
+ close.close();
+ }
+
+ @Test public void flushingPresenter() throws IOException {
+ class FP implements Fn.Presenter, Flushable {
+ int flush;
+
+ @Override
+ public Fn defineFn(String code, String... names) {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void displayPage(URL page, Runnable onPageLoad) {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void loadScript(Reader code) throws Exception {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void flush() throws IOException {
+ flush++;
+ }
+ }
+
+ FP p = new FP();
+ Closeable c1 = Fn.activate(p);
+ Closeable c2 = Fn.activate(p);
+ c2.close();
+ assertEquals(p.flush, 0, "No flush yet");
+ c1.close();
+ assertEquals(p.flush, 1, "Now flushed");
+ }
+
+ @BeforeMethod public void initPresenter() {
+ FnContext.currentPresenter(presenter);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/test/java/org/netbeans/html/boot/impl/JavaScriptProcesorTest.java
----------------------------------------------------------------------
diff --git a/boot/src/test/java/org/netbeans/html/boot/impl/JavaScriptProcesorTest.java b/boot/src/test/java/org/netbeans/html/boot/impl/JavaScriptProcesorTest.java
new file mode 100644
index 0000000..1ef07b5
--- /dev/null
+++ b/boot/src/test/java/org/netbeans/html/boot/impl/JavaScriptProcesorTest.java
@@ -0,0 +1,167 @@
+/**
+ * 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 org.netbeans.html.boot.impl;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Locale;
+import javax.tools.Diagnostic;
+import javax.tools.JavaFileObject;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public class JavaScriptProcesorTest {
+
+ @Test public void detectCallbackToNonExistingClass() throws IOException {
+ String code = "package x.y.z;\n"
+ + "import net.java.html.js.JavaScriptBody;\n"
+ + "class X {\n"
+ + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
+ + " \"r.@java.lang.Runable::run()();\"\n" // typo
+ + " )\n"
+ + " private static native void callback(Runnable r);\n"
+ + "}\n";
+
+ Compile c = Compile.create("", code);
+ c.assertErrors();
+ c.assertError("java.lang.Runable"); // typo
+ }
+
+ @Test public void detectCallbackToNonExistingMethod() throws IOException {
+ String code = "package x.y.z;\n"
+ + "import net.java.html.js.JavaScriptBody;\n"
+ + "class X {\n"
+ + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
+ + " \"r.@java.lang.Runnable::cancel()();\"\n"
+ + " )\n"
+ + " private static native void callback(Runnable r);\n"
+ + "}\n";
+
+ Compile c = Compile.create("", code);
+ c.assertErrors();
+ c.assertError("method cancel");
+ }
+
+ @Test public void detectCallbackToNonExistingParams() throws IOException {
+ String code = "package x.y.z;\n"
+ + "import net.java.html.js.JavaScriptBody;\n"
+ + "class X {\n"
+ + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
+ + " \"r.@java.lang.Runnable::run(I)(10);\"\n"
+ + " )\n"
+ + " private static native void callback(Runnable r);\n"
+ + "}\n";
+
+ Compile c = Compile.create("", code);
+ c.assertErrors();
+ c.assertError("wrong parameters: (I)");
+ }
+
+ @Test public void objectTypeParamsAreOK() throws IOException {
+ String code = "package x.y.z;\n"
+ + "import net.java.html.js.JavaScriptBody;\n"
+ + "class X {\n"
+ + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
+ + " \"r.@java.lang.Object::equals(Ljava/lang/Object;)(null);\"\n"
+ + " )\n"
+ + " private static native void testEqual(Object r);\n"
+ + "}\n";
+
+ Compile c = Compile.create("", code);
+ c.assertNoErrors();
+ }
+
+ @Test public void misorderNotified() throws IOException {
+ String code = "package x.y.z;\n"
+ + "import net.java.html.js.JavaScriptBody;\n"
+ + "class X {\n"
+ + " @JavaScriptBody(args={\"r\", \"a\", \"b\"}, body =\"\"\n"
+ + " )\n"
+ + " private static native void testEqual(Object p, String q, int r);\n"
+ + "}\n";
+
+ Compile c = Compile.create("", code);
+ List<Diagnostic<? extends JavaFileObject>> warnings = c.getDiagnostics(Diagnostic.Kind.WARNING);
+ assertTrue(warnings.size() >= 1, "There are warnings: " + warnings);
+ for (Diagnostic<? extends JavaFileObject> w : warnings) {
+ if (w.getMessage(Locale.US).contains("Actual method parameter names and args")) {
+ return;
+ }
+ }
+ fail("Expecting order warning: " + warnings);
+ }
+
+ @Test public void needJavaScriptBodyToUseResource() throws IOException {
+ String code = "package x.y.z;\n"
+ + "import net.java.html.js.JavaScriptResource;\n"
+ + "@JavaScriptResource(\"x.html\")\n"
+ + "class X {\n"
+ + " private static native void callback(Runnable r);\n"
+ + "}\n";
+
+ Compile c = Compile.create("", code);
+ c.assertErrors();
+ c.assertError("needs @JavaScriptBody");
+ }
+
+ @Test public void generatesCallbacksThatReturnObject() throws Exception {
+ Class<?> callbacksForTestPkg = Class.forName("org.netbeans.html.boot.impl.$JsCallbacks$");
+ Method m = callbacksForTestPkg.getDeclaredMethod("java_lang_Runnable$run$", Runnable.class);
+ assertEquals(m.getReturnType(), java.lang.Object.class, "All methods always return object");
+ }
+
+ @Test public void hasInstanceField() throws Exception {
+ Class<?> callbacksForTestPkg = Class.forName("org.netbeans.html.boot.impl.$JsCallbacks$");
+ Field f = callbacksForTestPkg.getDeclaredField("VM");
+ f.setAccessible(true);
+ assertTrue(callbacksForTestPkg.isInstance(f.get(null)), "Singleton field VM");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/test/java/org/netbeans/html/boot/impl/JsCallbackTest.java
----------------------------------------------------------------------
diff --git a/boot/src/test/java/org/netbeans/html/boot/impl/JsCallbackTest.java b/boot/src/test/java/org/netbeans/html/boot/impl/JsCallbackTest.java
new file mode 100644
index 0000000..5b68349
--- /dev/null
+++ b/boot/src/test/java/org/netbeans/html/boot/impl/JsCallbackTest.java
@@ -0,0 +1,86 @@
+/**
+ * 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 org.netbeans.html.boot.impl;
+
+import static org.testng.Assert.*;
+import org.testng.annotations.Test;
+
+/** Verify behavior of the callback parser.
+ *
+ * @author Jaroslav Tulach
+ */
+public class JsCallbackTest {
+
+ public JsCallbackTest() {
+ }
+ @Test public void missingTypeSpecification() {
+ String body = "console[attr] = function(msg) {\n"
+ + " @org.netbeans.html.charts.Main::log(msg);\n"
+ + "};\n";
+ JsCallback instance = new JsCallbackImpl();
+ try {
+ String result = instance.parse(body);
+ fail("The parsing should fail!");
+ } catch (IllegalStateException ex) {
+ // OK
+ }
+ }
+
+
+ public class JsCallbackImpl extends JsCallback {
+ private String ident;
+ private String fqn;
+ private String method;
+ private String params;
+
+ @Override
+ public CharSequence callMethod(String ident, String fqn, String method, String params) {
+ this.ident = ident;
+ this.fqn = fqn;
+ this.method = method;
+ this.params = params;
+ return "call";
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/test/java/org/netbeans/html/boot/impl/JsClassLoaderBase.java
----------------------------------------------------------------------
diff --git a/boot/src/test/java/org/netbeans/html/boot/impl/JsClassLoaderBase.java b/boot/src/test/java/org/netbeans/html/boot/impl/JsClassLoaderBase.java
new file mode 100644
index 0000000..9b458d2
--- /dev/null
+++ b/boot/src/test/java/org/netbeans/html/boot/impl/JsClassLoaderBase.java
@@ -0,0 +1,285 @@
+/**
+ * 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 org.netbeans.html.boot.impl;
+
+import java.io.Closeable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.Map;
+import org.netbeans.html.boot.spi.Fn;
+import org.testng.Assert;
+import static org.testng.Assert.*;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public class JsClassLoaderBase {
+ protected static Class<?> methodClass;
+
+ public JsClassLoaderBase() {
+ }
+
+ @BeforeMethod
+ public void assertClassDefined() {
+ assertNotNull(methodClass, "BeforeClass set up code should provide methodClass");
+ }
+
+ @Test public void noParamMethod() throws Throwable {
+ Method plus = methodClass.getMethod("fortyTwo");
+ try {
+ final java.lang.Object val = plus.invoke(null);
+ assertTrue(val instanceof Number, "A number returned " + val);
+ assertEquals(((Number)val).intValue(), 42);
+ } catch (InvocationTargetException ex) {
+ throw ex.getTargetException();
+ }
+ }
+
+ @Test public void testExecuteScript() throws Throwable {
+ Method plus = methodClass.getMethod("plus", int.class, int.class);
+ try {
+ assertEquals(plus.invoke(null, 10, 20), 30);
+ } catch (InvocationTargetException ex) {
+ throw ex.getTargetException();
+ }
+ }
+
+ @Test public void overloadedMethod() throws Throwable {
+ Method plus = methodClass.getMethod("plus", int.class);
+ try {
+ assertEquals(plus.invoke(null, 10), 10);
+ } catch (InvocationTargetException ex) {
+ throw ex.getTargetException();
+ }
+ }
+
+ @Test public void instanceMethod() throws Throwable {
+ Method plus = methodClass.getMethod("plusInst", int.class);
+ java.lang.Object inst = methodClass.newInstance();
+ try {
+ assertEquals(plus.invoke(inst, 10), 10);
+ } catch (InvocationTargetException ex) {
+ throw ex.getTargetException();
+ }
+ }
+
+ @Test public void staticThis() throws Throwable {
+ Method st = methodClass.getMethod("staticThis");
+ try {
+ assertNull(st.invoke(null));
+ } catch (InvocationTargetException ex) {
+ throw ex.getTargetException();
+ }
+ }
+
+ @Test public void getThis() throws Throwable {
+ java.lang.Object th = methodClass.newInstance();
+ Method st = methodClass.getMethod("getThis");
+ try {
+ assertEquals(st.invoke(th), th);
+ } catch (InvocationTargetException ex) {
+ throw ex.getTargetException();
+ }
+ }
+
+ @Test public void primitiveArrayReturn() throws Throwable {
+ Method st = methodClass.getMethod("both", double.class, double.class);
+ Throwable ex;
+ try {
+ java.lang.Object arr = st.invoke(null, 2, 5);
+ ex = null;
+ } catch (InvocationTargetException invoke) {
+ ex = invoke.getTargetException();
+ }
+ assertTrue(ex instanceof ClassCastException, "Primitive arrays aren't returned from JavaScript: " + ex);
+ }
+
+ @Test public void truth() throws Throwable {
+ Method st = methodClass.getMethod("truth");
+ assertTrue((st.getModifiers() & Modifier.STATIC) != 0, "Is static");
+ assertEquals(st.invoke(null), Boolean.TRUE, "Can return boolean");
+ }
+
+ @Test public void callback() throws Throwable {
+ class R implements Runnable {
+ int cnt;
+
+ @Override
+ public void run() {
+ cnt++;
+ }
+ }
+ R r = new R();
+
+ Method inc = methodClass.getMethod("callback", Runnable.class);
+ inc.invoke(null, r);
+
+ assertEquals(r.cnt, 1, "Callback happened");
+ }
+
+ @Test public void sumArray() throws Throwable {
+ Method st = methodClass.getMethod("sumArr", int[].class);
+ assertEquals(st.invoke(null, new int[] { 1, 2, 3 }), 6, "1+2+3 is six");
+ }
+
+ @Test public void javaScriptResource() throws Throwable {
+ try {
+ Method st = methodClass.getMethod("useExternalMul", int.class, int.class);
+ assertEquals(st.invoke(null, 6, 7), 42, "Meaning of JavaScript?");
+ } catch (InvocationTargetException ex) {
+ throw ex.getTargetException();
+ }
+ }
+
+ @Test public void callJavaScriptMethodOnOwnClass() throws Throwable {
+ try {
+ java.lang.Object thiz = methodClass.newInstance();
+ Method st = methodClass.getMethod("returnYourSelf", methodClass);
+ assertEquals(st.invoke(null, thiz), thiz, "Returns this");
+ } catch (InvocationTargetException ex) {
+ throw ex.getTargetException();
+ }
+ }
+
+ @Test public void callStaticJavaMethod() throws Throwable {
+ Method st = methodClass.getMethod("staticCallback", int.class, int.class);
+ assertEquals(st.invoke(null, 6, 7), 42, "Meaning of JavaScript?");
+ }
+
+ @Test public void callStaticStringParamMethod() throws Throwable {
+ Method st = methodClass.getMethod("parseInt", String.class);
+ assertEquals(st.invoke(null, "42"), 42, "Meaning of JavaScript?");
+ }
+
+ @Test public void passEnum() throws Throwable {
+ Class<?> enmClazz = methodClass.getDeclaredClasses()[0];
+ assertTrue(Enum.class.isAssignableFrom(enmClazz), "It is an enum: " + enmClazz);
+ Class<? extends Enum> enmClazz2 = enmClazz.asSubclass(Enum.class);
+ Method st = methodClass.getMethod("fromEnum", enmClazz);
+
+ java.lang.Object valueB = Enum.valueOf(enmClazz2, "B");
+ assertEquals(st.invoke(null, valueB), "B", "Converts to string");
+ }
+
+ @Test public void firstLong() throws Throwable {
+ Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
+ assertEquals(st.invoke(null, true, false, 10, 20), 10L, "Take first value");
+ }
+
+ @Test public void secondLong() throws Throwable {
+ Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
+ assertEquals(st.invoke(null, false, true, 10, 20), 20L, "Take 2nd value");
+ }
+
+ @Test public void bothLong() throws Throwable {
+ Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
+ assertEquals(st.invoke(null, true, true, 10, 20), 30L, "Take both values");
+ }
+
+ @Test public void recordError() throws Throwable {
+ Method st = methodClass.getMethod("recordError", java.lang.Object.class);
+ assertEquals(st.invoke(methodClass.newInstance(), "Hello"), "Hello", "The same parameter returned");
+ }
+
+ @Test public void plusOrMul() throws Throwable {
+ Method st = methodClass.getMethod("plusOrMul", int.class, int.class);
+ assertNotNull(Fn.activePresenter(), "Is there a presenter?");
+ Closeable c = Fn.activate(null);
+ try {
+ assertNull(Fn.activePresenter(), "No presenter now");
+ assertEquals(st.invoke(null, 6, 7), 42, "Mul in Java");
+ } finally {
+ c.close();
+ }
+ assertNotNull(Fn.activePresenter(), "Is there a presenter again");
+ assertEquals(st.invoke(null, 6, 7), 13, "Plus in JavaScript");
+ c = Fn.activate(null);
+ try {
+ assertNull(Fn.activePresenter(), "No presenter again");
+ assertEquals(st.invoke(null, 6, 7), 42, "Mul in Java");
+ } finally {
+ c.close();
+ }
+ assertNotNull(Fn.activePresenter(), "Is there a presenter again");
+ assertEquals(st.invoke(null, 6, 7), 13, "Plus in JavaScript again");
+ }
+
+ @Test public void arrayInOut() throws Throwable {
+ String[] arr = { "Ahoj" };
+ Method st = methodClass.getMethod("arr", java.lang.Object[].class);
+ java.lang.Object ret = st.invoke(null, (java.lang.Object) arr);
+ assertTrue(ret instanceof java.lang.Object[], "Expecting array: " + ret);
+ java.lang.Object[] res = (java.lang.Object[]) ret;
+ assertEquals(res.length, 1, "One element");
+ assertEquals(res[0], "Ahoj", "The right string");
+ }
+
+ @Test public void parametricCallback() throws Throwable {
+ Map<String,Number> map = new HashMap<String, Number>();
+ Method st = methodClass.getMethod("callParamTypes", Map.class, int.class);
+ st.invoke(null, map, 42);
+ assertEquals(map.get("key").intValue(), 42, "The right value");
+ }
+
+ @Test public void checkTheTypeOfThrownException() throws Throwable {
+ FnContext.currentPresenter(null);
+ assertNull(Fn.activePresenter(), "No presenter is activer right now");
+ java.lang.Object res = null;
+ try {
+ Method st = methodClass.getMethod("plus", int.class, int.class);
+ try {
+ res = st.invoke(null, 40, 2);
+ Assert.fail("Native method should throw IllegalStateException. Was: " + res);
+ } catch (InvocationTargetException ex) {
+ throw ex.getTargetException();
+ }
+ } catch (IllegalStateException ex) {
+ assertEquals(ex.getMessage(), "No presenter active. Use BrwsrCtx.execute!");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/test/java/org/netbeans/html/boot/impl/JsClassLoaderTest.java
----------------------------------------------------------------------
diff --git a/boot/src/test/java/org/netbeans/html/boot/impl/JsClassLoaderTest.java b/boot/src/test/java/org/netbeans/html/boot/impl/JsClassLoaderTest.java
new file mode 100644
index 0000000..d69a761
--- /dev/null
+++ b/boot/src/test/java/org/netbeans/html/boot/impl/JsClassLoaderTest.java
@@ -0,0 +1,161 @@
+/**
+ * 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 org.netbeans.html.boot.impl;
+
+import java.io.Closeable;
+import java.io.Reader;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import javax.script.Invocable;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import org.netbeans.html.boot.spi.Fn;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public class JsClassLoaderTest extends JsClassLoaderBase{
+ private static Fn.Presenter loader;
+
+ @BeforeClass
+ public static void setUpClass() throws Exception {
+ ScriptEngineManager sem = new ScriptEngineManager();
+ final ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
+
+ final URL my = JsClassLoaderTest.class.getProtectionDomain().getCodeSource().getLocation();
+ ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
+ final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
+ class MyCL extends FnUtils.JsClassLoaderImpl implements Fn.Presenter {
+
+ public MyCL(ClassLoader parent) {
+ super(parent, null, null);
+ }
+
+ @Override
+ protected URL findResource(String name) {
+ return ul.getResource(name);
+ }
+ @Override
+ public Fn defineFn(String code, String... names) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("(function() {");
+ sb.append("return function(");
+ String sep = "";
+ for (String n : names) {
+ sb.append(sep);
+ sb.append(n);
+ sep = ", ";
+ }
+ sb.append(") {");
+ sb.append(code);
+ sb.append("};");
+ sb.append("})()");
+ try {
+ final java.lang.Object val = eng.eval(sb.toString());
+ return new Fn(this) {
+ @Override
+ public java.lang.Object invoke(java.lang.Object thiz, java.lang.Object... args) throws Exception {
+ List<java.lang.Object> all = new ArrayList<java.lang.Object>(args.length + 1);
+ all.add(thiz == null ? val : thiz);
+ all.addAll(Arrays.asList(args));
+ Invocable inv = (Invocable)eng;
+ try {
+ java.lang.Object ret = inv.invokeMethod(val, "call", all.toArray());
+ return val.equals(ret) ? null : ret;
+ } catch (Exception ex) {
+ throw ex;
+ }
+ }
+ };
+ } catch (ScriptException ex) {
+ throw new LinkageError("Can't parse: " + sb, ex);
+ }
+ }
+
+ @Override
+ protected Enumeration<URL> findResources(String name) {
+ URL u = findResource(name);
+ List<URL> arr = new ArrayList<URL>();
+ if (u != null) {
+ arr.add(u);
+ }
+ return Collections.enumeration(arr);
+ }
+
+ @Override
+ public void loadScript(Reader code) throws ScriptException {
+ eng.eval(code);
+ }
+
+ @Override
+ public void displayPage(URL page, Runnable onPageLoad) {
+ throw new UnsupportedOperationException();
+ }
+ };
+
+ MyCL l = new MyCL(parent);
+ Closeable close = FnContext.activate(l);
+ methodClass = l.loadClass(JsMethods.class.getName());
+ close.close();
+ loader = l;
+ }
+
+ @BeforeMethod public void initPresenter() {
+ FnContext.currentPresenter(loader);
+ }
+
+ @AfterClass
+ public static void cleanUp() {
+ methodClass = null;
+ }
+}
\ No newline at end of file