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:53 UTC

[20/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-truffle/src/test/java/net/java/html/boot/truffle/TruffleJavaScriptTest.java
----------------------------------------------------------------------
diff --git a/boot-truffle/src/test/java/net/java/html/boot/truffle/TruffleJavaScriptTest.java b/boot-truffle/src/test/java/net/java/html/boot/truffle/TruffleJavaScriptTest.java
new file mode 100644
index 0000000..ac4c4f5
--- /dev/null
+++ b/boot-truffle/src/test/java/net/java/html/boot/truffle/TruffleJavaScriptTest.java
@@ -0,0 +1,164 @@
+/**
+ * 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.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executors;
+import net.java.html.boot.BrowserBuilder;
+import org.netbeans.html.boot.spi.Fn;
+import org.netbeans.html.json.tck.JavaScriptTCK;
+import org.netbeans.html.json.tck.KOTest;
+import org.testng.Assert;
+import org.testng.SkipException;
+import org.testng.annotations.Factory;
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public class TruffleJavaScriptTest {
+    private static Class<?> browserClass;
+    private static Fn.Presenter browserPresenter;
+    
+    public TruffleJavaScriptTest() {
+    }
+
+    @Factory public static Object[] compatibilityTests() throws Exception {
+        PolyglotEngine engine = PolyglotEngine.newBuilder().build();
+        PolyglotEngine.Value result = null;
+        try {
+            result = engine.eval(Source.fromText("6 * 7", "test.js").withMimeType("text/javascript"));
+        } catch (Exception notSupported) {
+            if (notSupported.getMessage().contains("text/javascript")) {
+                return new Object[] { new Skip(true, notSupported.getMessage()) };
+            }
+        }
+        assertEquals(42, result.as(Number.class).intValue(), "Executed OK");
+
+        final BrowserBuilder bb = BrowserBuilder.newBrowser(TrufflePresenters.create(SingleCase.JS)).
+            loadClass(TruffleJavaScriptTest.class).
+            loadPage("empty.html").
+            invoke("initialized");
+
+        Executors.newSingleThreadExecutor().submit(new Runnable() {
+            @Override
+            public void run() {
+                bb.showAndWait();
+            }
+        });
+
+        List<Object> res = new ArrayList<>();
+        Class<? extends Annotation> test = 
+            loadClass().getClassLoader().loadClass(KOTest.class.getName()).
+            asSubclass(Annotation.class);
+
+        Class[] arr = (Class[]) loadClass().getDeclaredMethod("tests").invoke(null);
+        for (Class c : arr) {
+            if (c.getSimpleName().contains("GC")) {
+                continue;
+            }
+            for (Method m : c.getMethods()) {
+                if (m.getAnnotation(test) != null) {
+                    res.add(new SingleCase(browserPresenter, m));
+                }
+            }
+        }
+        return res.toArray();
+    }
+
+    static synchronized Class<?> loadClass() throws InterruptedException {
+        while (browserClass == null) {
+            TruffleJavaScriptTest.class.wait();
+        }
+        return browserClass;
+    }
+    
+    public static synchronized void ready(Class<?> browserCls) throws Exception {
+        browserClass = browserCls;
+        browserPresenter = Fn.activePresenter();
+        TruffleJavaScriptTest.class.notifyAll();
+    }
+    
+    public static void initialized() throws Exception {
+        Assert.assertSame(TruffleJavaScriptTest.class.getClassLoader(),
+            ClassLoader.getSystemClassLoader(),
+            "No special classloaders"
+        );
+        TruffleJavaScriptTest.ready(Tck.class);
+    }
+
+    public static final class Tck extends JavaScriptTCK {
+
+        public static Class[] tests() {
+            return testClasses();
+        }
+    }
+
+    public static final class Skip {
+        private final String message;
+        private final boolean fail;
+
+        public Skip(String message) {
+            this(false, message);
+        }
+
+        Skip(boolean fail, String message) {
+            this.message = message;
+            this.fail = fail;
+        }
+
+        @Test
+        public void needsGraalVMToExecuteTheTests() {
+            if (fail) {
+                throw new SkipException(message);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/pom.xml
----------------------------------------------------------------------
diff --git a/boot/pom.xml b/boot/pom.xml
new file mode 100644
index 0000000..e1ec2ff
--- /dev/null
+++ b/boot/pom.xml
@@ -0,0 +1,106 @@
+<?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>
+  <groupId>org.netbeans.html</groupId>
+  <artifactId>net.java.html.boot</artifactId>
+  <version>2.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+  <name>Browser Bootstrap</name>
+  <url>http://maven.apache.org</url>
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <publicPackages>net.java.html.js,net.java.html.boot,org.netbeans.html.boot.spi</publicPackages>
+  </properties>
+  <build>
+      <plugins>
+          <plugin>
+              <groupId>org.apache.felix</groupId>
+              <artifactId>maven-bundle-plugin</artifactId>
+              <configuration>
+                  <instructions>
+                      <Agent-Class>org.netbeans.html.boot.impl.JsAgent</Agent-Class>
+                      <Premain-Class>org.netbeans.html.boot.impl.JsAgent</Premain-Class>
+                      <Eclipse-BuddyPolicy>dependent</Eclipse-BuddyPolicy>
+                      <Require-Capability>osgi.extender;resolution:=optional;filter:="(osgi.extender=osgi.serviceloader.processor)",osgi.serviceloader;filter:="(osgi.serviceloader=org.netbeans.html.boot.spi.Fn$Presenter)";cardinality:=multiple;resolution:=optional</Require-Capability>
+                  </instructions>
+              </configuration>
+          </plugin>
+      </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.ow2.asm</groupId>
+      <artifactId>asm</artifactId>
+      <type>jar</type>
+      <scope>provided</scope>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>org.testng</groupId>
+      <artifactId>testng</artifactId>
+      <scope>test</scope>
+      <type>jar</type>
+    </dependency>
+    <dependency>
+      <groupId>org.netbeans.api</groupId>
+      <artifactId>org-openide-util-lookup</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.netbeans.html</groupId>
+      <artifactId>net.java.html</artifactId>
+      <version>${project.version}</version>
+      <type>jar</type>
+    </dependency>
+  </dependencies>
+    <description>Builder to launch your Java/HTML based application.</description>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/main/java/net/java/html/boot/BrowserBuilder.java
----------------------------------------------------------------------
diff --git a/boot/src/main/java/net/java/html/boot/BrowserBuilder.java b/boot/src/main/java/net/java/html/boot/BrowserBuilder.java
new file mode 100644
index 0000000..3bb8d52
--- /dev/null
+++ b/boot/src/main/java/net/java/html/boot/BrowserBuilder.java
@@ -0,0 +1,519 @@
+/**
+ * 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.io.InputStream;
+import java.lang.reflect.Method;
+import java.net.HttpURLConnection;
+import java.net.JarURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.ServiceLoader;
+import java.util.concurrent.Executor;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import net.java.html.BrwsrCtx;
+import net.java.html.js.JavaScriptBody;
+import org.netbeans.html.boot.spi.Fn;
+import org.netbeans.html.boot.spi.Fn.Presenter;
+import org.netbeans.html.context.spi.Contexts;
+import org.netbeans.html.context.spi.Contexts.Id;
+import org.netbeans.html.boot.impl.FindResources;
+import org.netbeans.html.boot.impl.FnContext;
+
+/** Use this builder to launch your Java/HTML based application. Typical
+ * usage in a main method of your application looks like this: 
+ * <pre>
+ * 
+ * <b>public static void</b> <em>main</em>(String... args) {
+ *     BrowserBuilder.{@link #newBrowser newBrowser()}.
+ *          {@link #loadClass(java.lang.Class) loadClass(YourMain.class)}.
+ *          {@link #loadPage(java.lang.String) loadPage("index.html")}.
+ *          {@link #locale(java.util.Locale) locale}({@link Locale#getDefault()}).
+ *          {@link #invoke(java.lang.String, java.lang.String[]) invoke("initialized", args)}.
+ *          {@link #showAndWait()};
+ *     System.exit(0);
+ * }
+ * </pre>
+ * The above will load <code>YourMain</code> class via
+ * a special classloader, it will locate an <code>index.html</code> (relative
+ * to <code>YourMain</code> class) and show it in a browser window. When the
+ * initialization is over, a <b>public static</b> method <em>initialized</em>
+ * in <code>YourMain</code> will be called with provided string parameters.
+ * <p>
+ * This module provides only API for building browsers. To use it properly one
+ * also needs an implementation on the classpath of one's application. For example
+ * use: <pre>
+ * &lt;dependency&gt;
+ *   &lt;groupId&gt;org.netbeans.html&lt;/groupId&gt;
+ *   &lt;artifactId&gt;net.java.html.boot.fx&lt;/artifactId&gt;
+ *   &lt;scope&gt;runtime&lt;/scope&gt;
+ * &lt;/dependency&gt;
+ * </pre>
+ *
+ * @author Jaroslav Tulach
+ */
+public final class BrowserBuilder {
+    private static final Logger LOG = Logger.getLogger(BrowserBuilder.class.getName());
+    
+    private String resource;
+    private Class<?> clazz;
+    private Runnable onLoad;
+    private String methodName;
+    private String[] methodArgs;
+    private final Object[] context;
+    private ClassLoader loader;
+    private Locale locale;
+    
+    private BrowserBuilder(Object[] context) {
+        this.context = context;
+    }
+
+    /** Entry method to obtain a new browser builder. Follow by calling 
+     * its instance methods like {@link #loadClass(java.lang.Class)} and
+     * {@link #loadPage(java.lang.String)}.
+     * Since introduction of {@link Id technology identifiers} the 
+     * provided <code>context</code> objects are also passed to the 
+     * {@link BrwsrCtx context} when it is being 
+     * {@link Contexts#newBuilder(java.lang.Object...) created}
+     * and can influence the selection
+     * of available technologies 
+     * (like {@link org.netbeans.html.json.spi.Technology},
+     * {@link org.netbeans.html.json.spi.Transfer} or
+     * {@link org.netbeans.html.json.spi.WSTransfer}) by name.
+     * 
+     * @param context any instances that should be available to the builder -
+     *   implementation dependant
+     * @return new browser builder
+     */
+    public static BrowserBuilder newBrowser(Object... context) {
+        return new BrowserBuilder(context);
+    }
+    
+    /** The class to load when the browser is initialized. This class
+     * is loaded by a special classloader (that supports {@link JavaScriptBody}
+     * and co.). 
+     * 
+     * @param mainClass the class to load and resolve when the browser is ready
+     * @return this builder
+     */
+    public BrowserBuilder loadClass(Class<?> mainClass) {
+        this.clazz = mainClass;
+        return this;
+    }
+    
+    /** Allows one to specify a runnable that should be invoked when a load
+     * of a page is finished. This method may be used in addition or instead
+     * of {@link #loadClass(java.lang.Class)} and 
+     * {@link #invoke(java.lang.String, java.lang.String...)} methods.
+     * 
+     * @param r the code to run when the page is loaded
+     * @return this builder
+     * @since 0.8.1
+     */
+    public BrowserBuilder loadFinished(Runnable r) {
+        this.onLoad = r;
+        return this;
+    }
+
+    /** Page to load into the browser. If the <code>page</code> represents
+     * a {@link URL} known to the Java system, the URL is passed to the browser. 
+     * If system property <code>browser.rootdir</code> is specified, then a
+     * file <code>page</code> relative to this directory is used as the URL.
+     * If no such file exists, the system seeks for the 
+     * resource via {@link Class#getResource(java.lang.String)}
+     * method (relative to the {@link #loadClass(java.lang.Class) specified class}). 
+     * If such resource is not found, a file relative to the location JAR
+     * that contains the {@link #loadClass(java.lang.Class) main class} is 
+     * searched for.
+     * <p>
+     * The search honors provided {@link #locale}, if specified.
+     * E.g. it will prefer <code>index_cs.html</code> over <code>index.html</code>
+     * if the locale is set to <code>cs_CZ</code>.
+     * 
+     * @param page the location (relative, absolute, or URL) of a page to load
+     * @return this builder
+     */
+    public BrowserBuilder loadPage(String page) {
+        this.resource = page;
+        return this;
+    }
+    
+    /** Locale to use when searching for an initial {@link #loadPage(java.lang.String) page to load}.
+     * Localization is best done by providing different versions of the 
+     * initial page with appropriate suffixes (like <code>index_cs.html</code>).
+     * Then one can call this method with value of {@link Locale#getDefault()}
+     * to instruct the builder to use the user's current locale.
+     * 
+     * @param locale the locale to use or <code>null</code> if no suffix search should be performed
+     * @return this builder
+     * @since 1.0
+     */
+    public BrowserBuilder locale(Locale locale) {
+        this.locale = locale;
+        return this;
+    }
+    
+    /** Specifies callback method to notify the application that the browser is ready.
+     * There should be a <b>public static</b> method in the class specified
+     * by {@link #loadClass(java.lang.Class)} which takes an array of {@link String}
+     * argument. The method is called on the browser dispatch thread one
+     * the browser finishes loading of the {@link #loadPage(java.lang.String) HTML page}.
+     * 
+     * @param methodName name of a method to seek for
+     * @param args parameters to pass to the method
+     * @return this builder
+     */
+    public BrowserBuilder invoke(String methodName, String... args) {
+        this.methodName = methodName;
+        this.methodArgs = args;
+        return this;
+    }
+
+    /** Loader to use when searching for classes to initialize. 
+     * If specified, this loader is going to be used to load {@link Presenter}
+     * and {@link Contexts#fillInByProviders(java.lang.Class, org.netbeans.html.context.spi.Contexts.Builder) fill} {@link BrwsrCtx} in.
+     * Specifying special classloader may be useful in modular systems, 
+     * like OSGi, where one needs to load classes from many otherwise independent
+     * modules.
+     * 
+     * @param l the loader to use (or <code>null</code>)
+     * @return this builder
+     * @since 0.9
+     */
+    public BrowserBuilder classloader(ClassLoader l) {
+        this.loader = l;
+        return this;
+    }
+
+    /** Shows the browser, loads specified page in and executes the 
+     * {@link #invoke(java.lang.String, java.lang.String[]) initialization method}.
+     * The method returns when the browser is closed.
+     * 
+     * @throws NullPointerException if some of essential parameters (like {@link #loadPage(java.lang.String) page} or
+     *    {@link #loadClass(java.lang.Class) class} have not been specified
+     */
+    public void showAndWait() {
+        if (resource == null) {
+            throw new NullPointerException("Need to specify resource via loadPage method");
+        }
+        
+        final Class<?> myCls;
+        if (clazz != null) {
+            myCls = clazz;
+        } else if (onLoad != null) {
+            myCls = onLoad.getClass();
+        } else {
+            throw new NullPointerException("loadClass, neither loadFinished was called!");
+        }
+        IOException mal[] = { null };
+        URL url = findLocalizedResourceURL(resource, locale, mal, myCls);
+        
+        Fn.Presenter dfnr = null;
+        for (Object o : context) {
+            if (o instanceof Fn.Presenter) {
+                dfnr = (Fn.Presenter)o;
+                break;
+            }
+        }
+
+        if (dfnr == null && loader != null) for (Fn.Presenter o : ServiceLoader.load(Fn.Presenter.class, loader)) {
+            dfnr = o;
+            break;
+        }
+        
+        if (dfnr == null) for (Fn.Presenter o : ServiceLoader.load(Fn.Presenter.class)) {
+            dfnr = o;
+            break;
+        }
+        
+        if (dfnr == null) {
+            throw new IllegalStateException("Can't find any Fn.Presenter");
+        }
+        
+        final ClassLoader activeLoader;
+        if (loader != null) {
+            final URL res = FnContext.isJavaScriptCapable(loader);
+            if (res != null) {
+                throw new IllegalStateException("Loader " + loader + 
+                    " cannot resolve @JavaScriptBody, because of " + res
+                );
+            }
+            activeLoader = loader;
+        } else {
+            final URL res = FnContext.isJavaScriptCapable(myCls.getClassLoader());
+            if (res == null) {
+                activeLoader = myCls.getClassLoader();
+            } else {
+                FImpl impl = new FImpl(myCls.getClassLoader());
+                activeLoader = FnContext.newLoader(res, impl, dfnr, myCls.getClassLoader().getParent());
+                if (activeLoader == null) {
+                    throw new IllegalStateException("Cannot find asm-5.0.jar classes!");
+                }
+            }
+        }
+        
+        final Fn.Presenter dP = dfnr;
+
+        class OnPageLoad implements Runnable {
+            @Override
+            public void run() {
+                try {
+                    final Fn.Presenter aP = Fn.activePresenter();
+                    final Fn.Presenter currentP = aP != null ? aP : dP;
+                    
+                    Thread.currentThread().setContextClassLoader(activeLoader);
+                    final Class<?> newClazz = onLoad != null ?
+                        myCls :
+                        Class.forName(myCls.getName(), true, activeLoader);
+                    Contexts.Builder cb = Contexts.newBuilder(context);
+                    if (!Contexts.fillInByProviders(newClazz, cb)) {
+                        LOG.log(Level.WARNING, "Using empty technology for {0}", newClazz);
+                    }
+                    if (currentP instanceof Executor) {
+                        cb.register(Executor.class, (Executor)currentP, 1000);
+                    }
+                    cb.register(Fn.Presenter.class, currentP, 1000);
+                    BrwsrCtx c = cb.build();
+
+                    class CallInitMethod implements Runnable {
+                        @Override
+                        public void run() {
+                            Throwable firstError = null;
+                            if (onLoad != null) {
+                                try {
+                                    FnContext.currentPresenter(currentP);
+                                    onLoad.run();
+                                } catch (Throwable ex) {
+                                    firstError = ex;
+                                } finally {
+                                    FnContext.currentPresenter(null);
+                                }
+                            }
+                            INIT: if (methodName != null) {
+                                if (methodArgs.length == 0) {
+                                    try {
+                                        Method m = newClazz.getMethod(methodName);
+                                        FnContext.currentPresenter(currentP);
+                                        m.invoke(null);
+                                        firstError = null;
+                                        break INIT;
+                                    } catch (Throwable ex) {
+                                        firstError = ex;
+                                    } finally {
+                                        FnContext.currentPresenter(null);
+                                    }
+                                }
+                                try {
+                                    Method m = newClazz.getMethod(methodName, String[].class);
+                                    FnContext.currentPresenter(currentP);
+                                    m.invoke(m, (Object) methodArgs);
+                                    firstError = null;
+                                } catch (Throwable ex) {
+                                    LOG.log(Level.SEVERE, "Can't call " + methodName + " with args " + Arrays.toString(methodArgs), ex);
+                                } finally {
+                                    FnContext.currentPresenter(null);
+                                }
+                            }
+                            if (firstError != null) {
+                                LOG.log(Level.SEVERE, "Can't initialize the view", firstError);
+                            }
+                        }
+                    }
+                    
+                    c.execute(new CallInitMethod());
+                } catch (ClassNotFoundException ex) {
+                    LOG.log(Level.SEVERE, "Can't load " + myCls.getName(), ex);
+                }
+            }
+        }
+        dfnr.displayPage(url, new OnPageLoad());
+    }
+
+    private static URL findResourceURL(String resource, String suffix, IOException[] mal, Class<?> relativeTo) {
+        if (suffix != null) {
+            int lastDot = resource.lastIndexOf('.');
+            if (lastDot != -1) {
+                resource = resource.substring(0, lastDot) + suffix + resource.substring(lastDot);
+            } else {
+                resource = resource + suffix;
+            }
+        }
+        
+        URL url = null;
+        try {
+            String baseURL = System.getProperty("browser.rootdir"); // NOI18N
+            if (baseURL != null) {
+                URL u = new File(baseURL, resource).toURI().toURL();
+                if (isReal(u)) {
+                    url = u;
+                }
+            } 
+            
+            {
+                URL u = new URL(resource);
+                if (suffix == null || isReal(u)) {
+                    url = u;
+                }
+                return url;
+            }
+        } catch (MalformedURLException ex) {
+            mal[0] = ex;
+        }
+        
+        if (url == null) {
+            url = relativeTo.getResource(resource);
+        }
+        if (url == null) {
+            final ProtectionDomain pd = relativeTo.getProtectionDomain();
+            if (pd != null && pd.getCodeSource() != null) {
+                URL jar = pd.getCodeSource().getLocation();
+                try {
+                    URL u = new URL(jar, resource);
+                    if (isReal(u)) {
+                        url = u;
+                    }
+                } catch (MalformedURLException ex) {
+                    ex.initCause(mal[0]);
+                    mal[0] = ex;
+                }
+            }
+        }
+        if (url == null) {
+            URL res = BrowserBuilder.class.getResource("html4j.txt");
+            LOG.log(Level.FINE, "Found html4j {0}", res);
+            if (res != null) {
+                try {
+                    URLConnection c = res.openConnection();
+                    LOG.log(Level.FINE, "testing : {0}", c);
+                    if (c instanceof JarURLConnection) {
+                        JarURLConnection jc = (JarURLConnection) c;
+                        URL base = jc.getJarFileURL();
+                        for (int i = 0; i < 50; i++) {
+                            URL u = new URL(base, resource);
+                            if (isReal(u)) {
+                                url = u;
+                                break;
+                            }
+                            base = new URL(base, "..");
+                        }
+                    }
+                } catch (IOException ex) {
+                    mal[0] = ex;
+                }
+            }
+        }
+        return url;
+    }
+
+    static URL findLocalizedResourceURL(String resource, Locale l, IOException[] mal, Class<?> relativeTo) {
+        URL url = null;
+        if (l != null) {
+            url = findResourceURL(resource, "_" + l.getLanguage() + "_" + l.getCountry(), mal, relativeTo);
+            if (url != null) {
+                return url;
+            }
+            url = findResourceURL(resource, "_" + l.getLanguage(), mal, relativeTo);
+        }
+        if (url != null) {
+            return url;
+        }
+        return findResourceURL(resource, null, mal, relativeTo);
+    }
+    
+    private static boolean isReal(URL u) {
+        try {
+            URLConnection conn = u.openConnection();
+            if (conn instanceof HttpURLConnection) {
+                HttpURLConnection hc = (HttpURLConnection) conn;
+                hc.setReadTimeout(5000);
+                if (hc.getResponseCode() >= 300) {
+                    throw new IOException("Wrong code: " + hc.getResponseCode());
+                }
+            }
+            InputStream is = conn.getInputStream();
+            is.close();
+            LOG.log(Level.FINE, "found real url: {0}", u);
+            return true;
+        } catch (IOException ignore) {
+            LOG.log(Level.FINE, "Cannot open " + u, ignore);
+            return false;
+        }
+    }
+
+    private static final class FImpl implements FindResources {
+        final ClassLoader l;
+
+        public FImpl(ClassLoader l) {
+            this.l = l;
+        }
+
+        @Override
+        public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough) {
+            if (oneIsEnough) {
+                URL u = l.getResource(path);
+                if (u != null) {
+                    results.add(u);
+                }
+            } else {
+                try {
+                    Enumeration<URL> en = l.getResources(path);
+                    while (en.hasMoreElements()) {
+                        results.add(en.nextElement());
+                    }
+                } catch (IOException ex) {
+                    // no results
+                }
+            }
+        }
+        
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/main/java/net/java/html/boot/package.html
----------------------------------------------------------------------
diff --git a/boot/src/main/java/net/java/html/boot/package.html b/boot/src/main/java/net/java/html/boot/package.html
new file mode 100644
index 0000000..aea8c9b
--- /dev/null
+++ b/boot/src/main/java/net/java/html/boot/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>{@link net.java.html.boot.BrowserBuilder Builder} class to bootstrap your Java/HTML based application.</div>
+        See {@link net.java.html.boot.BrowserBuilder} for description how to
+        launch your application. Look at {@link net.java.html.js.JavaScriptBody}
+        and its usage in case you want to directly talk between Java and
+        JavaScript.
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/main/java/net/java/html/js/JavaScriptBody.java
----------------------------------------------------------------------
diff --git a/boot/src/main/java/net/java/html/js/JavaScriptBody.java b/boot/src/main/java/net/java/html/js/JavaScriptBody.java
new file mode 100644
index 0000000..01f4977
--- /dev/null
+++ b/boot/src/main/java/net/java/html/js/JavaScriptBody.java
@@ -0,0 +1,152 @@
+/**
+ * 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.js;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/** Put this annotation on a method to provide its special implementation
+ * in JavaScript. This is a way to define <em>native</em> methods that 
+ * interact with the surrounding JavaScript environment. Check the list
+ * <a href="package-summary.html">use-cases</a> to see real world
+ * use of this annotation.
+ * <p>
+ * Visit an <a target="_blank" href="http://dew.apidesign.org/dew/#7102188">on-line demo</a>
+ * to play with {@link JavaScriptBody} annotation for real.
+ *
+ * @author Jaroslav Tulach
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ ElementType.METHOD, ElementType.CONSTRUCTOR })
+public @interface JavaScriptBody {
+    /** Names of parameters for the method generated method that can
+     * be referenced from {@link #body()}.
+     * 
+     * @return array of the names of parameters for the method
+     *    in JavaScript
+     */
+    public String[] args();
+    
+    /** The actual body of the method in JavaScript. This string will be
+     * put into generated header (last character is '{') and footer (e.g. '}').
+     * The body can reference provided arguments. In case of non-static
+     * instance method it may reference <code>this</code>. 
+     * 
+     * @return JavaScript body of a function which can access {@link #args()} and possibly
+     * <code>this</code>
+     */
+    public String body();
+
+    /** Should a special syntax for calling back into Java object be turned on?
+     * The syntax begins with <b>{@code @}</b> followed by fully qualified
+     * package name of the class. Now followed by <b>::</b> and a method in
+     * the class followed by its parameters enclosed inside <b>(...)</b>.
+     * This is the syntax one can use to call <code>run()</code> 
+     * method of {@link Runnable}:
+     * <pre>r.@java.lang.Runnable::run()()</pre>.
+     * One can also call static methods. Just use:
+     * <pre>var ten = @java.lang.Integer::parseInt(Ljava/lang/String;)("10")</pre>
+     * 
+     * @return true, if the script should be scanned for special callback
+     *   syntax
+     */
+    public boolean javacall() default false;
+
+    /** Should we wait before the JavaScript snippet execution finishes?
+     * Or not. 
+     * <p>
+     * Some implementations that recognize the {@link JavaScriptBody} annotation
+     * need to reschedule the JavaScript execution into different thread and
+     * then it is easier for them to perform the execution asynchronously
+     * and not wait for the result of the execution. This may however be
+     * unexpected (for example when one awaits a callback into Java)
+     * and as such it has to be explicitly allowed by specifying
+     * <code>wait4js = false</code>. Such methods need to return <code>void</code>.
+     * <p>
+     * Implementations that execute the JavaScript synchronously may ignore
+     * this attribute.
+     * <p>
+     * Implementations that delay execution of JavaScript need to guarantee
+     * the order of snippets. Those that were submitted sooner, need to be
+     * executed sooner. Each snippet need to be executed in a timely manner
+     * (e.g. by a second, or so) even if there are no other calls made
+     * in the main program.
+     * <p>
+     * 
+     * @since 0.7.6
+     * @return <code>false</code> in case one allows asynchronous execution
+     *   of the JavaScript snippet
+     */
+    public boolean wait4js() default true;
+    
+    /** Controls garbage collection behavior of method parameters.
+     * In general JavaScript garbage
+     * collection system makes it close to impossible to find out whether
+     * an object is supposed to be still used or not. Some systems have
+     * an external hooks to find that out (like <em>JavaFX</em> <code>WebView</code>),
+     * in some systems this information is not important (like the 
+     * <a href="http://bck2brwsr.apidesign.org">Bck2Brwsr</a> VM running
+     * all in JavaScript), but other execution systems just can't find that
+     * out. To prevent memory leaks on such systems and help them manage
+     * memory more effectively, those who define JavaScript interfacing 
+     * methods may indicate whether the non-primitive parameters passed
+     * in should be hold only for the time of method invocation or 
+     * for the whole application lifetime.
+     * <p>
+     * The default value is <code>true</code> as that is compatible with
+     * previous behavior and also prevents unwanted surprises when something
+     * garbage collects pre-maturaly. Framework developers are however 
+     * encouraged to use <code>keepAlive=false</code> as much as possible.
+     * 
+     * @return whether Java objects passed as parameters of the method
+     *   should be made guaranteed to be available JavaScript
+     *   even after the method invocation is over (e.g. prevent them to be
+     *   garbage collected in Java until it is known they are not needed
+     *   from JavaScript at all).
+     * 
+     * @since 1.1
+     */
+    public boolean keepAlive() default true;
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/main/java/net/java/html/js/JavaScriptResource.java
----------------------------------------------------------------------
diff --git a/boot/src/main/java/net/java/html/js/JavaScriptResource.java b/boot/src/main/java/net/java/html/js/JavaScriptResource.java
new file mode 100644
index 0000000..c14d10e
--- /dev/null
+++ b/boot/src/main/java/net/java/html/js/JavaScriptResource.java
@@ -0,0 +1,70 @@
+/**
+ * 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.js;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/** Include JavaScript libraries into your application easily.
+ * Annotate a Java/JavaScript bridging class with this annotation and
+ * once one of the class {@code @}{@link JavaScriptBody} annotated methods
+ * is called, it is guaranteed the JavaScript interpreter pre-load
+ * the content of here is specified resource. All other 
+ * {@code @}{@link JavaScriptBody} methods can then access objects created
+ * by precessing this {@link JavaScriptResource#value() java script resource}.
+ * The list of
+ * <a href="package-summary.html#library">use-cases</a> includes sample use
+ * of this annotation.
+ *
+ * @author Jaroslav Tulach
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.TYPE)
+public @interface JavaScriptResource {
+    /** The JavaScript file to load in before associated class can execute.
+     * @return relative path with respect to the annotated class
+     */
+    public String value();
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/main/java/net/java/html/js/package.html
----------------------------------------------------------------------
diff --git a/boot/src/main/java/net/java/html/js/package.html b/boot/src/main/java/net/java/html/js/package.html
new file mode 100644
index 0000000..f8160c0
--- /dev/null
+++ b/boot/src/main/java/net/java/html/js/package.html
@@ -0,0 +1,483 @@
+<!--
+
+    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>Essential support for those who write <em>native</em> methods communicating directly with JavaScript.</div>
+        Mix your Java and JavaScript code seamlessly - perform calls from Java
+        to JavaScript and back with as much freedom as JavaScript gives you
+        and as much type safety you can get from Java. Execute your code
+        in a headless testing environment or in a 
+        <a href="http://wiki.apidesign.org/wiki/FXBrwsr">JavaFX WebView</a>. 
+        When done, deploy to <a href="http://bck2brwsr.apidesign.org">real browsers</a>.
+        
+        <h3>Simple Meaning of World</h3>
+        The whole support is build around @<a href="JavaScriptBody.html">JavaScriptBody</a>
+        annotation. Use it to create parametrised JavaScript snippet easily
+        accessible from Java:
+<pre>
+{@code @}{@link net.java.html.js.JavaScriptBody}(args = {"x", "y"}, body = "return x + y;")
+<b>private static native int</b> meaning(<b>int</b> x, <b>int</b> y);
+</pre>
+        The above defines method <em>meaning</em> which sums two JavaScript
+        objects together (being invoked inside of a JavaScript interpreter).
+        The <em>meaning</em> method now becomes a properly typed Java
+        surface to your JavaScript code which can be directly
+        called from the rest of your Java code:
+<pre>        
+<b>public static void</b> main(String... args) {
+  <b>assert</b> 42 == meaning(40, 2) : <em>"Meaning of World should be 42!"</em>;
+}
+</pre>
+        <em>Real code tip:</em> real classes using this technique are
+        available online:
+        <a target="top" href="http://hg.netbeans.org/html4j/file/release-0.7/boot/src/test/java/org/netbeans/html/boot/impl/JsMethods.java">JsMethods</a> and
+        <a target="top" href="http://hg.netbeans.org/html4j/file/release-0.7/json-tck/src/main/java/net/java/html/js/tests/Bodies.java">Bodies</a>.
+        <p></p>
+        <em>Editing hint:</em> one can see the list of arguments of the
+        <em>meaning</em> is now duplicated - it is once specified in Java, 
+        and once inside of the {@link net.java.html.js.JavaScriptBody} 
+        array of <code>args</code>. This is necessary to keep the names of 
+        arguments accessible during runtime. However don't despair - there
+        is a code completion for the value of <code>args</code> attribute!
+        Just type the Java signature first and then press Ctrl+Space and the
+        right parameter names will be inserted for you.
+        
+        <a name="#library"><h3>Including JavaScript Libraries</h3></a>
+
+        Large amount of JavaScript code is easier to be delivered in whole
+        files rather than {@link net.java.html.js.JavaScriptBody small code snippets} -
+        that is also possible thanks to {@link net.java.html.js.JavaScriptResource}
+        annotation. Imagine file <code>mul.js</code> with following content:
+<pre> 
+<b>function</b> <em>mul</em>(x, y) { <b>return</b> x * y; }
+</pre>
+        Place the file next to your class and reference it with 
+        {@link net.java.html.js.JavaScriptResource the annotation}:
+<pre>
+{@code @}{@link net.java.html.js.JavaScriptResource}("mul.js") <b>class</b> Mul {
+
+  {@code @}{@link net.java.html.js.JavaScriptBody}(args = { "x", "y" }, body = "return <b>mul</b>(x, y);")
+  <b>public static native int</b> multiply(int x, int y);
+
+  <b>public static void</b> main(String... args) {
+    <b>assert</b> 42 == multiply(6, 7) : <em>"Meaning of World should be 42!"</em>;
+  }
+}
+</pre>
+        All the Java methods annotated {@link net.java.html.js.JavaScriptBody}
+        can now reference everything that is in the <code>mul.js</code> file -
+        e.g. the body of the <code>multiply</code> method can reference the
+        function <code>mul</code> and use it.
+        <p></p>
+        <em>Real code tip:</em>
+        <a target="top" href="http://hg.netbeans.org/html4j/file/release-0.7/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java">this</a> 
+        is the way 
+        the <a target="top" href="http://knockoutjs.com">knockout.js</a> library
+        is included in its <em>ko4j</em> library.
+        
+        <h3>Callback to Java</h3>
+        
+        Often JavaScript code needs to call back into the Java classes.
+        For example when a button in a browser is pressed and your code would
+        like to invoke a runnable to handle such situation:
+<pre> 
+{@code @}{@link net.java.html.js.JavaScriptBody}(args = {"id", "r"}, {@link net.java.html.js.JavaScriptBody#javacall() javacall} = true, body = "\n" + 
+"       document.getElementById(id).onclick = function() {\n" + 
+"        r.<em>{@code @}java.lang.Runnable::run()</em>();\n" + 
+"       };\n" + 
+"    ")
+<b>public static native void</b> onClick(String id, Runnable r);
+</pre>
+        As can be seen, there is a special syntax (starting with <b>@</b>) to 
+        properly identify the right Java method to call on a Java object passed
+        into the JavaScript interpreter. The syntax starts with a fully
+        qualified name of the class, followed by <b>::</b> and name of the 
+        method including signature of its parameters. In case of runnable,
+        this is just <em>()</em> as the method has no parameters, but the
+        signature can be more complicated. For example in case of following method
+<pre><b>static int</b> compare(<b>int</b> i1, String s1, <b>int</b> i2, String s2)
+</pre>        
+        it would be <em>(ILjava/lang/String;ILjava/lang/String;)</em> (btw. the
+        return type is not included in the signature). The actual parameters 
+        then follows. The JavaScript call to such compare method would then
+        look like:
+<pre>{@code @}the.pkg.Clazz::compare(ILjava/lang/String;ILjava/lang/String;)(1, 'One', 2, 'Two');
+</pre>        
+        This syntax gives enough flexibility, helps to properly select one
+        of overloaded methods and follows the tradition of previous attempts to
+        provide JavaScript to Java calling conventions.
+        <p></p>
+        Please note that to turn the special Java callback syntax on, one
+        needs to set the {@link net.java.html.js.JavaScriptBody#javacall()}
+        attribute to <b>true</b>. The callback syntax consists of
+        following parts:
+        <p></p>
+        <pre>[instance.]@classname::methodname(signature)(arguments)</pre>
+        <ul>
+            <li><b>instance</b> - must be present when calling an 
+                instance method and must be absent when calling a 
+                static method</li>
+            <li><b>classname</b> - fully qualified name of the class in 
+                which the method is declared 
+            </li>
+            <li><b>signature</b> - internal JVM method signature 
+                (as specified at 
+                <a target="top" href="http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/types.html#wp16432">JNI type Signatures</a>) 
+                without the trailing signature of the method return type</li>
+            <li><b>arguments</b> - the actual values to pass to the called Java method
+            </li>
+        </ul>
+
+        <p>Here is the <a target="top" href="http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/types.html#wp16432">JNI type signatures table</a>
+            one can use to convert
+            Java parameters to JVM's internal <em>letter</em> based 
+            representation:</p>
+        
+        <table border=1 width='100%'>
+            <tr>
+                <td><b>Type Signature</b></td>
+                <td><b>Java Type</b></td>
+            </tr>
+            <tr>
+              <td>Z</td>
+              <td>boolean</td>
+            </tr>
+            <tr>
+              <td>B</td>
+              <td>byte</td>
+            </tr>
+            <tr>
+              <td>C</td>
+              <td>char</td>
+            </tr>
+            <tr>
+              <td>S</td>
+              <td>short</td>
+            </tr>
+            <tr>
+              <td>I</td>
+              <td>int</td>
+            </tr>
+            <tr>
+              <td>J</td>
+              <td>long</td>
+            </tr>
+            <tr>
+              <td>F</td>
+              <td>float</td>
+            </tr>
+            <tr>
+              <td>D</td>
+              <td>double</td>
+            </tr>
+            <tr>
+              <td>L fully-qualified-class ;</td>
+              <td>fully-qualified-class</td>
+            </tr>
+            <tr>
+              <td>[ type</td>
+              <td>type[]</td>
+            </tr>
+          </tbody>
+        </table>
+        <p></p>
+        <em>Editing hint:</em> The callback syntax may seem complicated at
+        first, however there is an associated <b>annotation processor</b> 
+        that checks the syntax and verifies the referenced class and
+        method with the requested signature exist. If it does not, the
+        <em>compilation fails offering correct alternatives</em>. 
+        Thus don't despair seeing the syntax, make sure you get the
+        fully qualified name of the callback class right. 
+        You'll get warning and help 
+        if there is a typo in the specified signature then -
+        during compilation of your code.
+        
+        <h3>Overloaded Methods</h3>
+        
+        Specifying the actual callback signature is important in case of 
+        overloaded methods. Imagine a class:
+<pre>
+<b>package</b> x.y.z;
+<b>class</b> Handler {
+  <b>int</b> pulse() {
+    <b>return</b> 1;
+  }
+  <b>int</b> pulse(<b>int</b> howMuch) {
+    <b>return</b> howMuch;
+  }
+  <b>int</b> pulse(<b>long</b> evenMore) {
+    <b>return</b> (<b>int</b>) (5 + evenMore);
+  }
+}</pre>        
+        you then need to choose in {@link net.java.html.js.JavaScriptBody} 
+        the appropriate method to call:
+<pre>
+{@code @}{@link net.java.html.js.JavaScriptBody}(args = { "h" }, javacall = <b>true</b>, <em>// you want to process the @ syntax</em>
+  body = "<b>return</b> h.@x.y.z.Handler::pulse()() +" + <em>// the call to no argument method</em>
+    "h.@x.y.z.Handler::pulse(I)(10) +" + <em>// the call to method with integer argument</em>
+    "h.@x.y.z.Handler::pulse(J)(10);" <em>// the call to method with long argument</em>
+  )
+  <b>static native void</b> threePulsesFromJavaScript(Handler h);
+  <b>static</b> {
+    <b>assert</b> 26 == threePulsesFromJavaScript(<b>new</b> Handler());
+  }
+</pre>
+        <p>
+        To avoid ambiguity, the specification of the correct signature is 
+        required on every call. However, to simplify the development,
+        there is an annotation processor to
+        verify the signature really refers to an existing method.
+        </p>
+        
+        <h3>Arrays by Copy</h3>
+        
+        It is possible to exchange arrays between Java and JavaScript. Some
+        implementations can pass arrays by reference, however in some systems
+        this is hard to achieve. To choose the least common denominator, 
+        the TCK for behavior of {@link net.java.html.js.JavaScriptBody} requires
+        the arrays to be always transfered by a copy. As such following code:
+        <pre>
+{@code @}{@link net.java.html.js.JavaScriptBody}(args = {"arr"}, body = "arr[0] = null;")
+<b>private static native void</b> uselessModify(String[] arr);
+<b>public static void</b> main(String... args) {
+  String[] hello = { "Hello", "World!" };
+  uselessModify(arr);
+  System.out.println(arr[0] + " " + arr[1]);
+}            
+</pre>
+        will still print <em>Hello World!</em> in spite the JavaScript code
+        sets the 0-th array element to <code>null</code>. Because the array
+        is passed as a copy, such assignment has no effect on the Java array.
+        <p></p>
+        In case one needs to modify an array in a JavaScript and use its 
+        values in Java, one has to return the array back as a return value:
+        <pre>        
+{@code @}{@link net.java.html.js.JavaScriptBody}(args = {"arr"}, body = "arr[0] = 'Ahoy'; return arr;")
+<b>private static native</b> Object[] usefulModify(String[] arr);
+<b>public static void</b> main(String... args) {
+  String[] hello = { "Hello", "World!" };
+  Object[] ret = usefulModify(arr);
+  System.out.println(ret[0] + " " + ret[1]);
+}            
+</pre>
+        now the program prints <em>Ahoy World!</em> as the modified array
+        is returned back and converted (by a copy) into a Java <code>Object[]</code>
+        (but of course the <code>ret != hello</code>). Usually the copy based
+        passing of arrays works OK. It is however good to keep it in mind to 
+        avoid unwanted surprises.
+        
+        <h3>Instance Reference to JavaScript Object</h3>
+        
+        When writing wrappers around existing JavaScript libraries, it may be
+        useful to hold a reference to some JavaScript object from a Java 
+        instance and use it later.
+<pre>
+<b>class</b> WrapperAroundJsObj {
+  <b>private final</b> Object js;
+
+  WrapperAroundJsObj() {
+    js = initValue();
+  }
+
+  <b>public void</b> set(int v) {
+    setValue(js, v);
+  }
+
+  {@link net.java.html.js.JavaScriptBody @JavaScriptBody}(args = {}, body = "return { value : 0 };")
+  <b>private static native</b> Object initValue();
+
+  {@link net.java.html.js.JavaScriptBody @JavaScriptBody}(
+    args = { "js", "v" }, body = "js.value = v;", wait4js = false
+  )
+  <b>private static native void</b> setValue(Object js, int v);
+}            
+</pre>      
+        The type of the Java reference is {@link java.lang.Object}. 
+        From a Java perspective it has no additional methods or fields, however
+        its properties can be manipulated from JavaScript. Send the object back
+        to JavaScript by passing it as a parameter of some method 
+        (like the <code>setValue</code> one) and perform necessary JavaScript
+        calls or changes on it.
+
+        <h3>undefined === null</h3>
+        <a name='undefined'></a>
+
+        JavaScript recognizes two <em>empty</em> values: <code>null</code> and
+        <code>undefined</code>. Java has just <code>null</code>.
+
+        For purposes of simplicity and easier inter-operability, <code>undefined</code>
+        values returned from {@link net.java.html.js.JavaScriptBody @JavaScriptBody}
+        annotated methods are converted to <code>null</code>. In the following
+        example both methods return <code>null</code>:
+<pre>
+  {@link net.java.html.js.JavaScriptBody @JavaScriptBody}(
+    args = {}, body = "var empty = {}; return empty.x;"
+  )
+  <b>private static native</b> Object returnUndefined();
+  {@link net.java.html.js.JavaScriptBody @JavaScriptBody}(
+    args = {}, body = "var empty = {}; empty.x = null; return empty.x;"
+  )
+  <b>private static native</b> Object returnNull();
+}
+</pre>
+        This is the behavior since version 1.4.
+        
+        <h3>Post Process Classes</h3>
+        <a name="post-process"></a>
+
+        Classes with {@link net.java.html.js.JavaScriptBody} annotated methods need to
+        be post processed before they can be used - e.g. their <code>native</code>
+        body needs to be generated to call into JavaScript (btw. the code is performed
+        via {@link org.netbeans.html.boot.spi.Fn}). There are three ways
+        such post processing can happen.
+        <p></p>
+        <b>Compile time</b> processing - this is the preferred method that
+        most of the <a href="http://html.java.net">Html Java APIs</a> are using. 
+        Just include following plugin configuration into your <code>pom.xml</code>
+        and your classes will be ready for execution as soon as <em>process-classes</em>
+        <a href="http://wiki.apidesign.org/wiki/Maven">Maven</a> phase is over:
+<pre> 
+&lt;plugin&gt;
+    &lt;groupId&gt;org.netbeans.html&lt;/groupId&gt;
+    &lt;artifactId&gt;html4j-maven-plugin&lt;/artifactId&gt;
+    &lt;version&gt;${net.java.html.version}&lt;/version&gt;
+    &lt;executions&gt;
+        &lt;execution&gt;
+            &lt;id&gt;js-classes&lt;/id&gt;
+            &lt;goals&gt;
+                &lt;goal&gt;process-js-annotations&lt;/goal&gt;
+            &lt;/goals&gt;
+        &lt;/execution&gt;
+    &lt;/executions&gt;
+&lt;/plugin&gt;
+</pre>
+        This plugin works in orchestration with 
+        <a href="http://wiki.apidesign.org/wiki/AnnotationProcessor">annotation
+        processor</a> associated with {@link net.java.html.js.JavaScriptBody}
+        and {@link net.java.html.js.JavaScriptResource} - the processor creates
+        list of files that need post-processing. The 
+        <a href="http://wiki.apidesign.org/wiki/Maven">Maven</a>
+        plugin reads these files, processes classes mentioned in them and 
+        modifies (and deletes at the end) the files to not include classes
+        already processed.
+        <p></p>
+        <b>Instrumentation Agent</b> - one can do processing in runtime 
+        using JDK's {@link java.lang.instrument.ClassFileTransformer instrumentation}
+        abilities. The JAR artifact of <code>org.netbeans.html:net.java.html.boot</code>
+        contains an <code>Agent-Class</code> and <code>Premain-Class</code> 
+        definitions in its manifest. As such one can launch the Java virtual
+        machine with
+<pre>
+$ java -javaagent:jarpath=net.java.html.boot-x.y.jar
+</pre>        
+        and the runtime will take care of processing bytecode of classes 
+        not yet processed in compile time before they are loaded into the
+        virtual machine. 
+        <p></p>
+        <b>Special classloading</b> - when booting your application with
+        {@link net.java.html.boot.BrowserBuilder} there is a 3rd option of
+        processing the classes. If there are some classes not yet processed
+        (remember the files listing them generated by the 
+        <a href="http://wiki.apidesign.org/wiki/AnnotationProcessor">annotation
+        processor</a>), the {@link net.java.html.boot.BrowserBuilder#showAndWait() launching method}
+        will create a special classloader to that does the processing before
+        loading the bytecode into the virtual machine.
+        <p></p>
+        The options are rich, however to avoid any troubles (as the runtime
+        processing needs to also include <code>asm-5.0.jar</code> on application
+        classpath), it is recommended
+        to perform the <b>compile time</b> processing.
+        
+        <h3>Getting Started</h3>
+        
+        There are many ways to start developing 
+        <a href="http://html.java.net">Html for Java</a> application. 
+        However to be sure one chooses the most recent setup, it is recommended
+        to switch to good old command line and use a 
+        <a href="http://wiki.apidesign.org/wiki/Knockout4Java">Maven archetype</a>
+        associated with every version of this project. Just type:
+<pre>      
+$ mvn archetype:generate \
+ -DarchetypeGroupId=org.apidesign.html \
+ -DarchetypeArtifactId=knockout4j-archetype \
+ -DarchetypeVersion=x.y
+</pre>
+        Answer few questions (for example choose myfirstbrwsrpage as artifactId) and then you can:
+<pre>
+$ cd myfirstbrwsrpage
+$ mvn process-classes exec:java
+</pre>
+        In a few seconds (or minutes if 
+        <a href="http://wiki.apidesign.org/wiki/Maven">Maven</a>
+        decides to download the whole Internet of dependencies) you should 
+        see a sample Hello World application. It is basically composed from one 
+        Java and one HTML file:
+<pre>
+$ ls src/main/java/**/DataModel.java
+$ ls src/main/webapp/pages/index.html
+</pre>
+        Play with them, modify them and enjoy
+        <a href="http://html.java.net">Html for Java</a>!
+        
+        <a name="debugging">
+        <h3>Mixed Java/JavaScript Debugging</h3>
+        </a>
+        
+        <p>
+        The following video shows how easy it is to use 
+        NetBeans 8.0, JDK8 to debug an application that intermixes Java 
+        and JavaScript calls. One can put breakpoints into Java part, 
+        as well as JavaScript source code, inspect Java as well 
+        as JavaScript variables and switch between these two 
+        languages without any restrictions.
+        </p>
+        
+        <iframe width="420" height="315" 
+            src="http://www.youtube.com/embed/EvaTejQDRwA" 
+            frameborder="0" allowfullscreen>
+        </iframe>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/main/java/org/netbeans/html/boot/impl/FindResources.java
----------------------------------------------------------------------
diff --git a/boot/src/main/java/org/netbeans/html/boot/impl/FindResources.java b/boot/src/main/java/org/netbeans/html/boot/impl/FindResources.java
new file mode 100644
index 0000000..6dd53f2
--- /dev/null
+++ b/boot/src/main/java/org/netbeans/html/boot/impl/FindResources.java
@@ -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.
+ */
+package org.netbeans.html.boot.impl;
+
+import java.net.URL;
+import java.util.Collection;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public interface FindResources {
+
+    public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough);
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/main/java/org/netbeans/html/boot/impl/FnContext.java
----------------------------------------------------------------------
diff --git a/boot/src/main/java/org/netbeans/html/boot/impl/FnContext.java b/boot/src/main/java/org/netbeans/html/boot/impl/FnContext.java
new file mode 100644
index 0000000..9bb1ebf
--- /dev/null
+++ b/boot/src/main/java/org/netbeans/html/boot/impl/FnContext.java
@@ -0,0 +1,165 @@
+/**
+ * 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.BufferedReader;
+import java.io.Closeable;
+import java.io.Flushable;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.netbeans.html.boot.spi.Fn;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public final class FnContext implements Closeable {
+    private static final Logger LOG = Logger.getLogger(FnContext.class.getName());
+    private static final FnContext DUMMY;
+    static {
+        DUMMY = new FnContext(null, null);
+        DUMMY.prev = DUMMY;
+    }
+
+    public static URL isJavaScriptCapable(ClassLoader l) {
+        if (l instanceof JsClassLoader) {
+            return null;
+        }
+        return l.getResource("META-INF/net.java.html.js.classes");
+    }
+
+    public static ClassLoader newLoader(URL res, FindResources impl, Fn.Presenter p, ClassLoader parent) {
+        StringWriter w = new StringWriter();
+        PrintWriter pw = new PrintWriter(w);
+        Throwable t;
+        try {
+            Method newLoader = Class.forName("org.netbeans.html.boot.impl.FnUtils") // NOI18N
+                .getMethod("newLoader", FindResources.class, Fn.Presenter.class, ClassLoader.class);
+            return (ClassLoader) newLoader.invoke(null, impl, p, parent);
+        } catch (LinkageError ex) {
+            t = ex;
+        } catch (Exception ex) {
+            t = ex;
+        }
+        pw.println("When using @JavaScriptBody methods, one needs to either:");
+        pw.println(" - include asm-5.0.jar on runtime classpath");
+        pw.println(" - post process classes, see http://bits.netbeans.org/html+java/dev/net/java/html/js/package-summary.html#post-process");
+        pw.append("However following classes has not been processed from ").println(res);
+        
+        try {
+            BufferedReader r = new BufferedReader(new InputStreamReader(res.openStream()));
+            for (;;) {
+                String line = r.readLine();
+                if (line == null) {
+                    break;
+                }
+                pw.append("  ").println(line);
+            }
+            r.close();
+        } catch (IOException io) {
+            pw.append("Cannot read ").println(res);
+            io.printStackTrace(pw);
+        }
+        pw.println("Cannot initialize asm-5.0.jar!");
+        pw.flush();
+        LOG.log(Level.SEVERE, w.toString(), t);
+        return null;
+    }
+
+    private Object prev;
+    private final Fn.Presenter current;
+    private FnContext(Fn.Presenter prevP, Fn.Presenter newP) {
+        this.current = newP;
+        this.prev = prevP;
+    }
+
+    @Override
+    public void close() throws IOException {
+        if (prev != this) {
+            currentPresenter((Fn.Presenter)prev);
+            prev = this;
+            if (current instanceof Flushable) {
+                ((Flushable)current).flush();
+            }
+        }
+    }
+/*
+    @Override
+    protected void finalize() throws Throwable {
+        if (prev != null) {
+            LOG.warning("Unclosed context!");
+        }
+    }
+*/
+    public static Closeable activate(Fn.Presenter newP) {
+        final Fn.Presenter oldP = currentPresenter(newP);
+        if (oldP == newP) {
+            return DUMMY;
+        }
+        return new FnContext(oldP, newP);
+    }
+    
+    
+    private static final ThreadLocal<Fn.Presenter> CURRENT = new ThreadLocal<Fn.Presenter>();
+
+    public static Fn.Presenter currentPresenter(Fn.Presenter p) {
+        Fn.Presenter prev = CURRENT.get();
+        CURRENT.set(p);
+        return prev;
+    }
+
+    public static Fn.Presenter currentPresenter(boolean fail) {
+        Fn.Presenter p = CURRENT.get();
+        if (p == null && fail) {
+            throw new IllegalStateException("No current WebView context around!");
+        }
+        return p;
+    }
+    
+}