Repository: incubator-netbeans-html4j
Updated Branches:
  refs/heads/master [created] 226089a5a


http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/src/main/javadoc/overview.html
----------------------------------------------------------------------
diff --git a/src/main/javadoc/overview.html b/src/main/javadoc/overview.html
new file mode 100644
index 0000000..850c0d7
--- /dev/null
+++ b/src/main/javadoc/overview.html
@@ -0,0 +1,623 @@
+<!--
+
+    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+    Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+
+    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+    Other names may be trademarks of their respective owners.
+
+    The contents of this file are subject to the terms of either the GNU
+    General Public License Version 2 only ("GPL") or the Common
+    Development and Distribution License("CDDL") (collectively, the
+    "License"). You may not use this file except in compliance with the
+    License. You can obtain a copy of the License at
+    http://www.netbeans.org/cddl-gplv2.html
+    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+    specific language governing permissions and limitations under the
+    License.  When distributing the software, include this License Header
+    Notice in each file and include the License file at
+    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+    particular file as subject to the "Classpath" exception as provided
+    by Oracle in the GPL Version 2 section of the License file that
+    accompanied this code. If applicable, add the following below the
+    License Header, with the fields enclosed by brackets [] replaced by
+    your own identifying information:
+    "Portions Copyrighted [year] [name of copyright owner]"
+
+    Contributor(s):
+
+    The Original Software is NetBeans. The Initial Developer of the Original
+    Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights 
Reserved.
+
+    If you wish your version of this file to be governed by only the CDDL
+    or only the GPL Version 2, indicate your decision by adding
+    "[Contributor] elects to include this software in this distribution
+    under the [CDDL or GPL Version 2] license." If you do not indicate a
+    single choice of license, a recipient has the option to distribute
+    your version of this file under either the CDDL, the GPL Version 2 or
+    to extend the choice of license to its licensees as provided above.
+    However, if you add GPL Version 2 code and therefore, elected the GPL
+    Version 2 license, then the option applies only if the new code is
+    made subject to such option by the copyright holder.
+
+-->
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>HTML for Java APIs</title>
+        <meta charset="UTF-8">
+        <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    </head>
+    <body>
+        <p>
+         Use Java to write application logic; Use HTML5 to render the UI;
+         {@link net.java.html.json.Model Animate an HTML page from Java}
+         (see <a target="_blank" 
href="http://dew.apidesign.org/dew/#7212206";>Duke being rotated</a> by CSS);
+         Use {@link net.java.html.json.OnReceive REST} or
+         <a href="net/java/html/json/doc-files/websockets.html">WebSockets</a>;
+         interact with <a 
href="net/java/html/js/package-summary.html">JavaScript</a>;
+         Get the best of both worlds!
+
+         The goal of these APIs is to use full featured Java runtime
+         (like real <a target="_blank" 
href="http://wiki.apidesign.org/wiki/HotSpot";>HotSpot VM</a>),
+         but still rely on a very lightweight rendering technology
+         (so it can potentially fit
+         <a target="_blank" 
href="http://bck2brwsr.apidesign.org";>Bck2Brwsr</a> and definitely
+         to various types of phones). What can be more lightweight
+         (from a browser perspective) than
+         <a target="_blank" 
href="http://wiki.apidesign.org/wiki/HTML";>HTML</a>!?
+         By default we use {@link net.java.html.boot.fx JavaFX's WebView}
+         component to display the <a target="_blank" 
href="http://wiki.apidesign.org/wiki/HTML";>HTML</a>.
+         We eliminate the need to manipulate the DOM directly,
+         there is a special {@link net.java.html.json Java to Knockout.js 
binding}.
+         As a result the <a target="_blank" href="http://knockoutjs.com";>HTML 
uses Knockout.js syntax</a>,
+         yet the application code can be written in Java.
+        </p>
+
+        <h3>New features in version 1.4</h3>
+
+        Both values <code>null</code> and <code>undefined</code> are
+        <a href="net/java/html/js/package-summary.html#undefined">treated as 
null</a>.
+        Better behavior under <a target="_blank" 
href="https://netbeans.org/bugzilla/show_bug.cgi?id=259132";>
+        multi-threaded load</a>.
+        Integration with <a 
href="net/java/html/boot/truffle/package-summary.html">Truffle</a>.
+
+        <h3>Improvements in version 1.3</h3>
+
+        {@link net.java.html.json.Model Model classes} can have 
+        {@link net.java.html.json.Model#instance() per-instance private data}.
+        {@link net.java.html.json.Model Model classes} can generate
+        builder-like construction methods if builder
+        {@link net.java.html.json.Model#builder() prefix} is specified.
+        {@link net.java.html.json.Property#mutable} can be <code>false</code>
+        to define a non-mutable (almost constant) property. That
+        in case of <em>Knockout</em> bindings means: the property is
+        represented by a plain value rather than an observable in the 
JavaScript
+        object. The <em>JavaFX</em> presenter can be executed in headless mode 
-
+        just specify <code>-Dfxpresenter.headless=true</code> when launching
+        its virtual machine and no window will be shown. This is particularly
+        useful for testing. Configure your <em>surefire</em> or 
<em>failsafe</em>
+        plugins like: <pre>
+&lt;plugin&gt;
+  &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
+  &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;
+  &lt;version&gt;2.13&lt;/version&gt;
+  &lt;configuration&gt;
+      &lt;systemPropertyVariables&gt;
+          &lt;fxpresenter.headless&gt;true&lt;/fxpresenter.headless&gt;
+      &lt;/systemPropertyVariables&gt;
+  &lt;/configuration&gt;
+&lt;/plugin&gt;
+</pre>
+        OSGi headers are now <a target="_blank" 
href="https://netbeans.org/bugzilla/show_bug.cgi?id=256696";>
+            enterprise OSGi ready</a>.
+        Switched to <a target="_blank" 
href="https://netbeans.org/bugzilla/show_bug.cgi?id=257130";>minified version 
3.4.0</a>
+        of <a target="_blank" href="http://knockoutjs.com";>knockout.js</a>.
+        Better support for <a target="_blank" 
href="https://netbeans.org/bugzilla/show_bug.cgi?id=257348";>
+        recursive @Model definitions</a>.
+        New module <code>org.netbeans.html:xhr4j</code> provides implementation
+        of {@link org.netbeans.html.json.spi.Transfer} with
+        {@link org.netbeans.html.context.spi.Contexts.Id technology identifier}
+        <b>xhr4j</b> - this module can be used to
+        <a target="_blank" 
href='https://netbeans.org/bugzilla/show_bug.cgi?id=257849'>workaround 
limitations
+        of CORS</a> by handling the {@link net.java.html.json.OnReceive}
+        connections in Java.
+
+        <h3>What's Been Improved in Version 1.2.3?</h3>
+
+        One can control {@link net.java.html.json.OnReceive#headers() HTTP 
request headers}
+        when connecting to server using the {@link 
net.java.html.json.OnReceive}
+        annotation. It is possible to have
+        {@link net.java.html.json.ComputedProperty#write() writable computed 
properties}.
+        There is an easy way to enable <a target="_blank" 
href="http://getfirebug.com/";>Firebug</a> in
+        the JavaFX based Web View -
+        just run with <code>-Dfirebug.lite=true</code> as
+        <a target="_blank" 
href="https://www.youtube.com/watch?v=2rxwY-QJiLo";>this video</a>
+        demonstrates.
+        Bugfix of issues <a target="_blank" 
href='https://netbeans.org/bugzilla/show_bug.cgi?id=250503'>250503</a>,
+        <a target="_blank" 
href='https://netbeans.org/bugzilla/show_bug.cgi?id=252987'>252987</a>.
+
+        <h3>What's New in Version 1.1?</h3>
+
+        <p>
+            The content of a {@link net.java.html.BrwsrCtx context}
+            can be selected by registering implementations under specific
+            {@link org.netbeans.html.context.spi.Contexts.Id technology 
identifiers}
+            and requesting them during
+            {@link 
org.netbeans.html.context.spi.Contexts#newBuilder(java.lang.Object...) 
construction}
+            of the context. <code>org.netbeans.html:ko4j</code> module's 
implementation
+            offers <b>ko4j</b>, <b>xhr</b> and <b>websocket</b> identifiers
+            for its registered services
+            (e.g. {@link org.netbeans.html.json.spi.Technology},
+            {@link org.netbeans.html.json.spi.Transfer} and
+            {@link org.netbeans.html.json.spi.WSTransfer}).
+            <code>org.netbeans.html:ko-ws-tyrus</code>
+            module registers its
+            {@link org.netbeans.html.json.spi.Transfer Java based JSON} and
+            {@link org.netbeans.html.json.spi.WSTransfer WebSocket} 
implementations
+            under the name <b>tyrus</b>.
+        </p>
+        <p>
+            A particular DOM subtree
+            that a <a target="_blank" 
href="http://knockoutjs.com";>knockout.js</a> model gets
+            applied to can be selected by using
+            {@link 
net.java.html.json.Models#applyBindings(java.lang.Object,java.lang.String)
+            Models.applyBindings(m, id)} with an id of an HTML element.
+            There is new {@link net.java.html.json.Model#targetId()} attribute
+            which controls behavior of the generated 
<code>applyBindings</code> method.
+            If <em>specified and non-empty</em>, then the generated method
+            will call {@link 
net.java.html.json.Models#applyBindings(java.lang.Object,java.lang.String)}
+            with <code>this</code> and the provided {@link 
net.java.html.json.Model#targetId() target id}.
+            If <em>specified, but left empty</em>, then the generated method
+            calls {@link 
net.java.html.json.Models#applyBindings(java.lang.Object)}.
+            <em>If unspecified</em>, the method will <b>not</b> be generated 
at all
+            (a change with respect to older versions). However one can
+            still use {@link 
net.java.html.json.Models#applyBindings(java.lang.Object)}
+            or {@link 
net.java.html.json.Models#applyBindings(java.lang.Object,java.lang.String)}
+            to perform the association of any model with the page element.
+        </p>
+        <p>
+            Memory model when using Knockout bindings has been improved
+            (required additions of two new methods:
+            {@link org.netbeans.html.json.spi.PropertyBinding#weak()} and
+            {@link org.netbeans.html.json.spi.FunctionBinding#weak()}) and
+            now the Java {@link net.java.html.json.Model models} can garbage 
collect,
+            when no longer used. Library writers that use
+            {@link net.java.html.js.JavaScriptBody} annotation can also
+            control garbage collection behavior of method arguments by
+            setting {@link net.java.html.js.JavaScriptBody#keepAlive() 
keepAlive=false}
+            attribute.
+        </p>
+
+        <h3>What's New in Version 1.0?</h3>
+
+        <p>
+            {@link net.java.html.json.Property#array() Array properties} are 
now
+            mutable from the <a href="http://knockoutjs.com";>knockout.js</a>
+            point of view (required {@link 
org.netbeans.html.json.spi.Proto.Type#replaceValue one SPI change}).
+            The page lookup mechanism can use {@link 
net.java.html.boot.BrowserBuilder#locale(java.util.Locale) locale}
+            to load localized a page with appropriate suffix.
+            All SPI were moved under the NetBeans namespace - e.g.
+            {@link org.netbeans.html.boot.spi},
+            {@link org.netbeans.html.context.spi},
+            {@link org.netbeans.html.json.spi},
+            {@link org.netbeans.html.sound.spi}, and also
+            {@link org.netbeans.html.json.tck}. Methods annotated
+            with {@link net.java.html.js.JavaScriptBody} annotation and
+            without fallback Java code now throw {@link 
java.lang.IllegalStateException}
+            with a message suggesting to switch to proper
+            {@link net.java.html.BrwsrCtx#execute browser context} to
+            prevent endless debugging when one forgets to do so.
+        </p>
+
+        <p>
+        What's new in older versions? Click the
+        <a href="#" onclick="return showHistoric(true)">link</a>
+        to view even more
+        <a href="#" onclick="return showHistoric(true)">historic changes</a> 
below:
+        </p>
+
+        <a name="historic.changes"></a>
+        <div id="historic.changes">
+            <script>
+            function showHistoric(show) {
+                var e = document.getElementById("historic.changes");
+                if (show) {
+                    e.style.display="block";
+                } else {
+                    e.style.display="none";
+                }
+                return false;
+            }
+            showHistoric(false);
+            </script>
+
+        <h3>What's New in Version 0.9?</h3>
+
+        <p>
+            System can run in {@link 
net.java.html.boot.BrowserBuilder#classloader(java.lang.ClassLoader) Felix OSGi 
container} (originally only Equinox).
+            {@link net.java.html.json.ComputedProperty Derived properties}
+            now deeply check changes in other {@link net.java.html.json.Model 
model
+            classes} they depend on and recompute their values accordingly.
+            <a target="_blank" href="http://knockoutjs.com";>Knockout.js</a> 
library has been updated
+            to version 3.2.0.
+        </p>
+
+        <h3>What's New in 0.8.x Versions?</h3>
+
+        <p>
+            Setters or array properties on classes generated by {@link 
net.java.html.json.Model}
+            annotation can be accessed from any thread. {@link 
org.netbeans.html.sound.spi.AudioEnvironment}
+            can be registered into {@link net.java.html.BrwsrCtx}. There is
+            a {@link net.java.html.json.Models#parse(net.java.html.BrwsrCtx, 
java.lang.Class, java.io.InputStream, java.util.Collection)  method}
+            to parse a JSON array and convert it into
+            {@link net.java.html.json.Model model classes}.
+            Improved behavior of <code>enum</code> values in
+            {@link net.java.html.json.Model knockout bindings}.
+        </p>
+
+        <p>
+            Few bugfixes for better portability.
+            New API for {@link net.java.html.boot.script.Scripts headless 
execution}
+            on top of <em>Nashorn</em> - does not run <em>knockout for 
Java</em>
+            fully yet
+            (reported as <a 
href="https://bugs.openjdk.java.net/browse/JDK-8046013";>JDK-8046013</a>),
+            however even in current state it is quite
+            {@link net.java.html.boot.script.Scripts useful for testing}
+            of
+            {@link net.java.html.js Java/JavaScript interactions}.
+        </p>
+
+        <p>
+            {@link net.java.html.boot.fx.FXBrowsers} has been extended
+            with new helper methods to make it easier to use HTML+Java
+            API in existing JavaFX applications.
+            The annotation processor is made
+            more robust with respect to errors in callback syntax of
+            {@link net.java.html.js.JavaScriptBody} body parameter.
+            Javadoc of {@link net.java.html.BrwsrCtx#execute} method
+            has been improved based on a failure of its usability study.
+            There can be additional parameters to methods annotated by
+            {@link net.java.html.json.OnReceive} that allows one to
+            pass state when a JSON call is made and use it when it finishes.
+            The mechanism of discovery of sibling HTML page has been
+            extended to work on systems that don't support
+            {@link java.lang.Class#getProtectionDomain}.
+        </p>
+
+        <p>
+            The first argument of method annotated by
+            {@link net.java.html.json.OnReceive} annotation has to
+            be the associated {@link net.java.html.json.Model model class}.
+        </p>
+
+        <p>
+            {@link net.java.html.json.OnReceive} annotation now accepts
+            {@link java.util.List} of data values as second argument
+            (previously required an array).
+        </p>
+
+
+        <h3>What's New in 0.7.x Versions?</h3>
+
+        <p>
+            {@link net.java.html.js.JavaScriptBody} annotation has new 
attribute
+            {@link net.java.html.js.JavaScriptBody#wait4js()} which allows
+            asynchronous execution. Libraries using
+            {@link net.java.html.js.JavaScriptBody} are urged to use this
+            new attribute as much as possible, as it can speed up execution
+            in certain environments.
+        </p>
+
+        <p>
+            Use {@link net.java.html.BrwsrCtx#execute(java.lang.Runnable)} in
+            multi-threaded environment to execute your code on the browser 
thread.
+            See example
+            {@link net.java.html.BrwsrCtx#execute(java.lang.Runnable) using 
Java timer}.
+        </p>
+        </div>
+
+        <h3>Interesting Entry Points</h3>
+
+        <p>Learn how to {@link net.java.html.json.Model animate an HTML page 
from Java}
+            without referencing single HTML element from the Java code.
+        </p>
+        <p>Use {@link net.java.html.json.OnReceive JSON} to communicate
+            with REST based server API.
+        </p>
+        <p>Use <a 
href="net/java/html/json/doc-files/websockets.html">WebSockets</a>
+            and JSON.
+        </p>
+        <p>Call JavaScript methods from Java and vice versa, via
+            <a href="net/java/html/js/package-summary.html">JavaScriptBody</a>.
+        </p>
+
+        <h3>Getting Started</h3>
+
+        This <b>HTML/Java</b> API is used by
+        <a target="_blank" 
href="https://platform.netbeans.org/tutorials/nbm-dukescript.html";>
+        NetBeans Platform</a> as well as other project. The smoothest way
+        to get started is to follow the
+        <a target="_blank" 
href="https://dukescript.com/getting_started.html";>getting started</a>
+        tutorial. In case one wants to stick with a <em>Maven</em> and command
+        line, one can follow
+        <a target="_blank" 
href="https://dukescript.com/update/2015/02/05/New-Version-of-Dukescript.html";>
+            these instructions<a>, make sure at least
+        <em>JDK7</em> is your installed Java and type:
+        <pre>
+$ mvn archetype:generate \
+ -DarchetypeGroupId=com.dukescript.archetype \
+ -DarchetypeArtifactId=knockout4j-archetype \
+ -DarchetypeVersion=0.11 <em># or newer version, if available</em>
+        </pre>
+        Answer few questions (for example choose <em>myfirstbrwsrpage</em> as 
artifactId)
+        and then you can:
+        <pre>
+$ cd myfirstbrwsrpage
+$ mvn install
+$ mvn -f client/pom.xml process-classes exec:exec
+        </pre>
+        In a few seconds (or minutes if
+        <a target="_blank" 
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.
+        Immediatelly you can be
+        <a target="_blank" 
href="https://dukescript.com/best/practices/2015/04/12/no-redeploys.html";>
+        productive without any redeploys</a> - even more productive than
+        with plain JavaScript!
+        <p>
+        The application is rendered in a
+        <a target="_blank" 
href="http://wiki.apidesign.org/wiki/JavaFX";>JavaFX</a>
+        web view component (that of course requires your JDK to come
+        with <a target="_blank" 
href="http://wiki.apidesign.org/wiki/JavaFX";>JavaFX</a>;
+        <a target="_blank" 
href="http://www.oracle.com/technetwork/java/javase/downloads/index.html";>JDK7
+            and JDK8 from Oracle</a> contain everything that is needed).
+        The generated application is built around one
+        Java source (uses the {@link net.java.html.json.Model} annotation to
+        auto-generate another <code>Data.java</code> class during compilation)
+        and one HTML file (uses the <a target="_blank" 
href="http://knockoutjs.com";>Knockout</a>
+        syntax to <code>data-bind</code> the HTML elements to the
+        generated <code>Data</code> model):
+        <pre>
+$ ls client/src/main/java/**/DataModel.java
+$ ls client/src/main/webapp/pages/index.html
+        </pre>
+        That is all you need to get started. Play with the sources,
+        modify them and enjoy
+        <a target="_blank" href="http://html.java.net";>Html for Java</a>!
+
+        <h2>IDE Support</h2>
+
+        <p>
+            This API is part of <a target="_blank"
+            href="http://netbeans.org";>NetBeans.org</a> project and as such
+            it works naturally with the <a target="_blank"
+            href="https://netbeans.org/features/index.html";>NetBeans IDE</a>.
+            On the other hand, the API is using nothing NetBeans specific,
+            it builds on standard Java6 APIs and as such it shall work fine
+            in any IDE.
+        </p>
+
+        <p>
+            A lot of work is done by
+            <a href="http://wiki.apidesign.org/wiki/AnnotationProcessor";>
+            annotation processors</a>
+            that generate various boiler plate code during compilation. This
+            is a standard part of Java since JDK6, but for example Eclipse
+            is known not to deal with processors well and developers using
+            it need to be careful. IntelliJ users hasn't reported any issues
+            and of course, NetBeans IDE support for
+            <a 
href="http://wiki.apidesign.org/wiki/AnnotationProcessor";>processors</a>
+            is outstanding.
+        </p>
+
+        <p>
+            When using {@link net.java.html.js.JavaScriptBody} annotation, it 
is
+            useful to do a bit of post processing of classes. There is a
+            <a href="http://wiki.apidesign.org/wiki/Maven";>Maven</a>
+            plugin for that.
+            NetBeans IDE will invoke it when doing a build. Other IDEs may
+            need some hint to do so.
+            Anyway: If one does not see all (generated) sources or is getting
+            {@link java.lang.LinkageError}s when executing the application,
+            switch to command line and do clean build
+            from there:
+        </p>
+        <pre>$ mvn clean install</pre>
+        <p>
+            If that succeeds, your IDE of choice will hopefully
+            pick the generated sources up and present the result of the build
+            properly. If not,
+            <a href="https://netbeans.org/downloads/";>download NetBeans</a>,
+            you will be pleasantly
+            surprised - for example with our excellent
+            <a 
href="net/java/html/js/package-summary.html#debugging">Java/JavaScript
+            debugging</a> support.
+        </p>
+
+        <a name="deploy">
+        <h2>Deploy Your Application</h2>
+        </a>
+
+        <p>
+        It is not goal of this documentation to list all possible ways
+        to package and deploy applications which use this API. However it is
+        important for new comers to see the benefits of using the
+        <a href="http://html.java.net";>HTML for Java</a> API and as such
+        let's list at least few bundling options, known to work at the time of 
writing
+        this documentation.
+        </p>
+
+        <p>
+        First of all, this is a <em>client technology</em>. You write client 
applications
+        with it which may, but need not connect to a server. You don't need
+        Tomcat or WebLogic to deploy
+        <a href="http://html.java.net";>HTML for Java</a> applications.
+        </p>
+
+        <p>
+            <img 
src='https://rawgit.com/jtulach/minesweeper/877b7983b1c1a157ebb85850896bcf04d7f5c7f2/client-web/src/main/webapp/resources/javafx_logo.jpg'
 width="64"
+                 height="64" align="left"/>
+            The sample project generated by
+            <code>org.apidesign.html knockout4j-archetype</code> is configured
+            to use <a href="http://wiki.apidesign.org/wiki/JavaFX";>JavaFX</a>
+            as the rendering technology. This setup is primarily suitable for
+            development - it needs no special packaging, starts quickly and
+            allows you to use classical HotSpot VM debuggers. A final
+            artifact from the build is also a ZIP file which you can use
+            and distribute to your users. Good for desktop applications.
+        </p>
+
+        <p>
+            <img 
src='https://rawgit.com/jtulach/minesweeper/877b7983b1c1a157ebb85850896bcf04d7f5c7f2/client-web/src/main/webapp/resources/netbeans_logo.jpg'
 width="64"
+                 height="64" align="right"/>
+            <img 
src='https://rawgit.com/jtulach/minesweeper/877b7983b1c1a157ebb85850896bcf04d7f5c7f2/client-web/src/main/webapp/resources/eclipse_logo.png'
 width="64"
+                 height="64" align="right"/>
+            All the <a href="http://html.java.net";>HTML for Java</a> libraries
+            are packaged as <a 
href="http://wiki.apidesign.org/wiki/OSGi";>OSGi</a>
+            bundles and as such they can easily be run in NetBeans as well as
+            in Eclipse. As a result one can use
+            <a href="http://wiki.apidesign.org/wiki/OSGi";>OSGi</a>
+            and have a common module system for both platforms. In addition to 
that
+            one can render using
+            HTML and have a common UI in both platforms. In such case
+            your application would be packaged as a set of
+            <a href="http://wiki.apidesign.org/wiki/OSGi";>OSGi</a> bundles.
+            Read
+            <a href="http://wiki.apidesign.org/wiki/HTML";>more</a>...
+        </p>
+
+        <p>
+            <img 
src='https://rawgit.com/jtulach/minesweeper/877b7983b1c1a157ebb85850896bcf04d7f5c7f2/client-web/src/main/webapp/resources/chrome_logo.png'
 width="64"
+                 height="64" align="left"/>
+            <img 
src='https://rawgit.com/jtulach/minesweeper/877b7983b1c1a157ebb85850896bcf04d7f5c7f2/client-web/src/main/webapp/resources/safari_logo.png'
 width="64"
+                 height="64" align="left"/>
+            <img 
src='https://rawgit.com/jtulach/minesweeper/877b7983b1c1a157ebb85850896bcf04d7f5c7f2/client-web/src/main/webapp/resources/ie_logo.png'
 width="64"
+                 height="64" align="left"/>
+            <img 
src='https://rawgit.com/jtulach/minesweeper/877b7983b1c1a157ebb85850896bcf04d7f5c7f2/client-web/src/main/webapp/resources/firefox_logo.png'
 width="64"
+                 height="64" align="left"/>
+
+            There is more and more attempts to execute Java bytecode
+            in a browser, without any special Java plugin installed.
+            The <a href="http://html.java.net";>HTML for Java</a> is
+            carefully designed to produce lightweight, well performing
+            applications even on such restricted environments. It uses
+            no reflection calls and that allows to statically pre-compile
+            the applications into JavaScript. One of such environments
+            is called <a target="_blank" 
href="http://wiki.apidesign.org/wiki/Bck2Brwsr";>Bck2Brwsr</a>,
+            another <a target="_blank" 
href="http://wiki.apidesign.org/wiki/TeaVM";>TeaVM</a>. Both support the
+            {@link net.java.html.js.JavaScriptBody} annotation. Read
+            <a target="_blank" 
href="http://wiki.apidesign.org/wiki/Bck2BrwsrViaCLI";>more</a> or play
+            a minesweeper game packaged for your browser
+            (of course <a target="_blank"
+                href="https://github.com/jtulach/minesweeper";>written</a> in 
Java):
+        </p>
+
+        <script type="text/html" id="field">
+            <style type="text/css">
+                table.field td {
+                    padding: 4px;
+                    width: 18px;
+                    height: 18px;
+                    font-size: 1.5em;
+                    border: 1px solid black;
+                }
+                table.field td.UNKNOWN {
+                    background-color: #D6E4E1;
+                    cursor: pointer;
+                }
+                table.field td.EXPLOSION {
+                    background-color: #A31E39;
+                }
+                table.field td.DISCOVERED {
+                    background-color: #9DB2B1;
+                }
+            </style>
+            <table class="field">
+                <tbody>
+                    <!-- ko foreach: rows -->
+                    <tr>
+                        <!-- ko foreach: columns -->
+                        <td data-bind="css: style, click: $parents[1].click" >
+                            <div data-bind='html: html'></div>
+                        </td>
+                        <!-- /ko -->
+                    </tr>
+                    <!-- /ko -->
+                </tbody>
+            </table>
+        </script>
+
+        <center>
+        <div id="minesweeper" style="background-color: #f0f0f0; align: center">
+        <div data-bind="template: { name : 'field', if: fieldShowing }"></div>
+        </div>
+        </center>
+
+        <!-- boot bck2brwsr -->
+        <script type="text/javascript" 
src="https://rawgit.com/jtulach/minesweeper/877b7983b1c1a157ebb85850896bcf04d7f5c7f2/client-web/src/main/webapp/resources/teavm.js";></script>
+        <script>
+            var vm = new VM();
+            vm.loadClass('org.apidesign.demo.minesweeper.MainBrwsr');
+        </script>
+
+        <p>
+            <img 
src='https://rawgit.com/jtulach/minesweeper/877b7983b1c1a157ebb85850896bcf04d7f5c7f2/client-web/src/main/webapp/resources/ios_logo.jpg'
 width="64"
+                 height="64" align="right"/>
+            <img 
src='https://rawgit.com/jtulach/minesweeper/877b7983b1c1a157ebb85850896bcf04d7f5c7f2/client-web/src/main/webapp/resources/android_logo.jpg'
 width="64"
+                 height="64" align="right"/>
+
+            Now when we have seen that the
+            <a href="http://html.java.net";>HTML for Java</a> applications
+            can run on any modern browser, we can ask whether they can also
+            fit into a phone!? Yes, they can and especially to phones
+            that can execute Java code already! Just by changing your
+            packaging you can create an APK file and deploy it to your
+            Android phone.
+            Read <a target="_blank" 
href="http://wiki.apidesign.org/wiki/DlvkBrwsr";>more</a>
+            or install <a target="_blank" 
href="https://play.google.com/store/apps/details?id=org.apidesign.demo.minesweeper";>
+                Fair Minesweeper for Android</a>...
+        </p>
+        <p>
+            In case you'd like your application to reach out to second biggest
+            group of smartphone users, don't despair: It
+            seems the set of devices that can execute
+            <a href="http://html.java.net";>HTML for Java</a> applications
+            has been extended to <em>iPads</em> and <em>iPhones</em>. Get the
+            <a target="_blank" 
href="http://wiki.apidesign.org/wiki/IBrwsr";>details here</a>
+            and play <a target="_blank" 
href="https://itunes.apple.com/us/app/fair-minesweeper/id903688146";>
+                Fair Minesweeper on iOS</a>!
+        </p>
+        <p>
+            Convinced it makes sense to use
+            <a href="http://html.java.net";>HTML for Java</a>
+            APIs for writing applications that are
+            <em>written once, displayed anywhere</em>? Or do you have an
+            environment which is not supported? In such case you can bring
+            <a href="http://html.java.net";>HTML for Java</a>
+            to your environment yourself. Just implement your own
+            {@link org.netbeans.html.boot.spi.Fn.Presenter}!
+        </p>
+
+        <h2>Other Resources</h2>
+
+        <img src="net/java/html/json/doc-files/DukeHTML.png" width="256" 
height="184" alt="Duke and HTML5. Together at last!" align="right"/>
+
+        The javadoc for latest and previous versions is also available
+        online:
+        <ul>
+            <li>Current <a target="_blank" 
href="http://bits.netbeans.org/html+java/dev/";>development</a> version
+            <li>Version <a target="_blank" 
href="http://bits.netbeans.org/html+java/1.2.3";>1.2.3</a>
+            <li>Version <a target="_blank" 
href="http://bits.netbeans.org/html+java/1.1";>1.1</a>
+            <li>Version <a target="_blank" 
href="http://bits.netbeans.org/html+java/1.0";>1.0</a>
+            <li>Version <a target="_blank" 
href="http://bits.netbeans.org/html+java/0.9";>0.9</a>
+                and historic ones (<a target="_blank" 
href="http://bits.netbeans.org/html+java/0.8.3";>0.8.3</a>,
+                <a target="_blank" 
href="http://bits.netbeans.org/html+java/0.8.2";>0.8.2</a>,
+                <a target="_blank" 
href="http://bits.netbeans.org/html+java/0.8.1";>0.8.1</a>,
+                <a target="_blank" 
href="http://bits.netbeans.org/html+java/0.8";>0.8</a>, and
+                <a target="_blank" 
href="http://bits.netbeans.org/html+java/0.7.5";>0.7.5</a>)
+            </li>
+        </ul>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/xhr4j/pom.xml
----------------------------------------------------------------------
diff --git a/xhr4j/pom.xml b/xhr4j/pom.xml
new file mode 100644
index 0000000..947ef26
--- /dev/null
+++ b/xhr4j/pom.xml
@@ -0,0 +1,166 @@
+<?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>xhr4j</artifactId>
+  <version>2.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+  <name>XHR via Java</name>
+  <url>http://maven.apache.org</url>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.netbeans.html</groupId>
+                <artifactId>html4j-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <bundleSymbolicName>org.netbeans.html.xhr4j</bundleSymbolicName>
+  </properties>
+  <dependencies>
+    <!-- compile only deps -->
+    <dependency>
+      <groupId>org.netbeans.api</groupId>
+      <artifactId>org-openide-util-lookup</artifactId>
+      <type>jar</type>
+      <scope>provided</scope>
+    </dependency>
+
+    <!-- compile + runtime -->      
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>net.java.html</artifactId>
+      <version>${project.version}</version>
+      <type>jar</type>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>net.java.html.json</artifactId>
+      <version>${project.version}</version>
+      <type>jar</type>
+    </dependency>
+    <!-- test only deps -->
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>net.java.html.boot</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
+      <type>jar</type>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>net.java.html.json.tck</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+      <type>jar</type>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>ko4j</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+      <type>jar</type>
+    </dependency>
+    <dependency>
+      <groupId>org.glassfish.grizzly</groupId>
+      <artifactId>grizzly-http-server-core</artifactId>
+      <version>${grizzly.version}</version>
+      <scope>test</scope>
+      <type>jar</type>
+    </dependency>
+    <dependency>
+      <groupId>org.glassfish.grizzly</groupId>
+      <artifactId>grizzly-websockets-server</artifactId>
+      <version>${grizzly.version}</version>
+      <scope>test</scope>
+      <type>jar</type>
+    </dependency>
+    <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>net.java.html.boot.fx</artifactId>
+        <version>${project.version}</version>
+        <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.glassfish.grizzly</groupId>
+      <artifactId>grizzly-http-server</artifactId>
+      <version>${grizzly.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+        <groupId>org.glassfish.grizzly</groupId>
+        <artifactId>grizzly-http-servlet</artifactId>
+        <version>${grizzly.version}</version>
+        <scope>test</scope>
+    </dependency>    
+    <dependency>
+        <groupId>javax.servlet</groupId>
+        <artifactId>javax.servlet-api</artifactId>
+        <scope>test</scope>
+    </dependency>
+  </dependencies>
+    <description>Implementation module with support for XHR via Java.
+Use it to workaround CORS limitations.</description>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/xhr4j/src/main/java/org/netbeans/html/xhr4j/LoadJSON.java
----------------------------------------------------------------------
diff --git a/xhr4j/src/main/java/org/netbeans/html/xhr4j/LoadJSON.java 
b/xhr4j/src/main/java/org/netbeans/html/xhr4j/LoadJSON.java
new file mode 100644
index 0000000..78ac78a
--- /dev/null
+++ b/xhr4j/src/main/java/org/netbeans/html/xhr4j/LoadJSON.java
@@ -0,0 +1,274 @@
+/**
+ * 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.xhr4j;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PushbackInputStream;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.logging.Logger;
+import net.java.html.js.JavaScriptBody;
+import org.netbeans.html.json.spi.JSONCall;
+
+/** This is an implementation package - just
+ * include its JAR on classpath and use official {@link Context} API
+ * to access the functionality.
+ *
+ * @author Jaroslav Tulach
+ */
+final class LoadJSON implements Runnable {
+    private static final Logger LOG = 
Logger.getLogger(LoadJSON.class.getName());
+    private static final Executor REQ = Executors.newCachedThreadPool(new 
ThreadFactory() {
+        @Override
+        public Thread newThread(Runnable runnable) {
+            Thread thread = 
Executors.defaultThreadFactory().newThread(runnable);
+            thread.setDaemon(true);
+            thread.setName("xhr4j daemon");
+            return thread;
+        }
+    });
+
+    private final JSONCall call;
+    private final URL base;
+
+
+    private LoadJSON(JSONCall call) {
+        this.call = call;
+        this.base = null;
+    }
+
+    public static void loadJSON(JSONCall call) {
+        assert !"WebSocket".equals(call.getMethod());
+        REQ.execute(new LoadJSON((call)));
+    }
+
+    @Override
+    public void run() {
+        final String url;
+        Throwable error = null;
+        Object json = null;
+
+        if (call.isJSONP()) {
+            url = call.composeURL("dummy");
+        } else {
+            url = call.composeURL(null);
+        }
+        try {
+            final URL u = new URL(base, url.replace(" ", "%20"));
+            URLConnection conn = u.openConnection();
+            if (call.isDoOutput()) {
+                conn.setDoOutput(true);
+            }
+            String h = call.getHeaders();
+            if (h != null) {
+                int pos = 0;
+                while (pos < h.length()) {
+                    int tagEnd = h.indexOf(':', pos);
+                    if (tagEnd == -1) {
+                        break;
+                    }
+                    int r = h.indexOf('\r', tagEnd);
+                    int n = h.indexOf('\n', tagEnd);
+                    if (r == -1) {
+                        r = h.length();
+                    }
+                    if (n == -1) {
+                        n = h.length();
+                    }
+                    String key = h.substring(pos, tagEnd).trim();
+                    String val = h.substring(tagEnd + 1, Math.min(r, 
n)).trim();
+                    conn.setRequestProperty(key, val);;
+                    pos = Math.max(r, n);
+                }
+            }
+            if (call.getMethod() != null && conn instanceof HttpURLConnection) 
{
+                ((HttpURLConnection) conn).setRequestMethod(call.getMethod());
+            }
+            if (call.isDoOutput()) {
+                final OutputStream os = conn.getOutputStream();
+                call.writeData(os);
+                os.flush();
+            }
+            final PushbackInputStream is = new PushbackInputStream(
+                conn.getInputStream(), 1
+            );
+            boolean[] arrayOrString = { false, false };
+            detectJSONType(call.isJSONP(), is, arrayOrString);
+            String response = readStream(is);
+            if (call.isJSONP()) {
+                response = '(' + response;
+            }
+            json = new Result(response, arrayOrString[0], arrayOrString[1]);
+        } catch (IOException ex) {
+            error = ex;
+        } finally {
+            if (error != null) {
+                call.notifyError(error);
+            } else {
+                call.notifySuccess(json);
+            }
+        }
+    }
+
+    private static final class Result implements Callable<Object> {
+        private final String response;
+        private final boolean array;
+        private final boolean plain;
+
+        Result(String response, boolean array, boolean plain) {
+            this.response = response;
+            this.array = array;
+            this.plain = plain;
+        }
+
+        @Override
+        public Object call() throws Exception {
+            if (plain) {
+                return response;
+            } else {
+                if (array) {
+                    Object r = parse(response);
+                    Object[] arr = r instanceof Object[] ? (Object[])r : new 
Object[] { r };
+                    for (int i = 0; i < arr.length; i++) {
+                        arr[i] = new JSObjToStr(response, arr[i]);
+                    }
+                    return arr;
+                } else {
+                    return new JSObjToStr(response, parse(response));
+                }
+            }
+        }
+    }
+    private static final class JSObjToStr {
+        final String str;
+        final Object obj;
+
+        public JSObjToStr(Object str, Object obj) {
+            this.str = str == null ? "" : str.toString();
+            this.obj = obj;
+        }
+
+        @Override
+        public String toString() {
+            return str;
+        }
+    }
+
+    static String readStream(InputStream is) throws IOException, 
UnsupportedEncodingException {
+        Reader r = new InputStreamReader(is, "UTF-8");
+        StringBuilder sb = new StringBuilder();
+        char[] arr = new char[4096];
+        for (;;) {
+            int len = r.read(arr);
+            if (len == -1) {
+                break;
+            }
+            sb.append(arr, 0, len);
+        }
+        return sb.toString();
+    }
+
+    private static void detectJSONType(boolean skipAnything, final 
PushbackInputStream is, boolean[] arrayOrString) throws IOException {
+        for (;;) {
+            int ch = is.read();
+            if (ch == -1) {
+                arrayOrString[1] = true;
+                break;
+            }
+            if (Character.isWhitespace(ch)) {
+                continue;
+            }
+
+            if (ch == '[') {
+                is.unread(ch);
+                arrayOrString[0] = true;
+                break;
+            }
+            if (ch == '{') {
+                is.unread(ch);
+                break;
+            }
+            if (!skipAnything) {
+                is.unread(ch);
+                arrayOrString[1] = true;
+                break;
+            }
+        }
+    }
+
+    @JavaScriptBody(args = {"object", "property"}, body =
+        "var ret;\n" + 
+        "if (property === null) ret = object;\n" + 
+        "else if (object === null) ret = null;\n" + 
+        "else ret = object[property];\n" + 
+        "return ret ? (typeof ko === 'undefined' ? ret : 
ko.utils.unwrapObservable(ret)) : null;"
+    )
+    private static Object getProperty(Object object, String property) {
+        return null;
+    }
+
+    @JavaScriptBody(args = {"s"}, body = "return eval('(' + s + ')');")
+    static Object parse(String s) {
+        throw new IllegalStateException("No parser context for " + s);
+    }
+
+    static void extractJSON(Object js, String[] props, Object[] values) {
+        if (js instanceof JSObjToStr) {
+            js = ((JSObjToStr)js).obj;
+        }
+        for (int i = 0; i < props.length; i++) {
+            values[i] = getProperty(js, props[i]);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/xhr4j/src/main/java/org/netbeans/html/xhr4j/XmlHttpResourceContext.java
----------------------------------------------------------------------
diff --git 
a/xhr4j/src/main/java/org/netbeans/html/xhr4j/XmlHttpResourceContext.java 
b/xhr4j/src/main/java/org/netbeans/html/xhr4j/XmlHttpResourceContext.java
new file mode 100644
index 0000000..4b3f02f
--- /dev/null
+++ b/xhr4j/src/main/java/org/netbeans/html/xhr4j/XmlHttpResourceContext.java
@@ -0,0 +1,88 @@
+/**
+ * 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.xhr4j;
+
+import java.io.IOException;
+import java.io.InputStream;
+import net.java.html.json.OnReceive;
+import org.netbeans.html.context.spi.Contexts;
+import org.netbeans.html.json.spi.JSONCall;
+import org.netbeans.html.json.spi.Transfer;
+import org.openide.util.lookup.ServiceProvider;
+
+/** Implementation module with support for XHR via Java.
+ * Handles {@link OnReceive} requests by using Java to connect to given
+ * URL and then parsing it via JavaScript. Use this module if you have
+ * problems with CORS - as the Java connection isn't restricted by CORS
+ * rules.
+ * 
+ * Registers {@link Transfer} technology at position <code>50</code>.
+ * The {@link Contexts.Id} of the technology is <b>xhr4j</b>.
+ * 
+ * @author Jaroslav Tulach
+ * @since 1.3
+ */
[email protected]("xhr4j")
+@ServiceProvider(service = Contexts.Provider.class)
+public final class XmlHttpResourceContext
+implements Contexts.Provider, Transfer {
+    @Override
+    public void fillContext(Contexts.Builder context, Class<?> requestor) {
+        context.register(Transfer.class, this, 50);
+    }
+
+    @Override
+    public void extract(Object obj, String[] props, Object[] values) {
+        LoadJSON.extractJSON(obj, props, values);
+    }
+
+    @Override
+    public Object toJSON(InputStream is) throws IOException {
+        return LoadJSON.parse(LoadJSON.readStream(is));
+    }
+
+    @Override
+    public void loadJSON(JSONCall call) {
+        LoadJSON.loadJSON(call);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/xhr4j/src/test/java/org/netbeans/html/xhr4j/JsonDynamicHTTP.java
----------------------------------------------------------------------
diff --git a/xhr4j/src/test/java/org/netbeans/html/xhr4j/JsonDynamicHTTP.java 
b/xhr4j/src/test/java/org/netbeans/html/xhr4j/JsonDynamicHTTP.java
new file mode 100644
index 0000000..d114468
--- /dev/null
+++ b/xhr4j/src/test/java/org/netbeans/html/xhr4j/JsonDynamicHTTP.java
@@ -0,0 +1,262 @@
+/**
+ * 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.xhr4j;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.glassfish.grizzly.PortRange;
+import org.glassfish.grizzly.http.server.HttpHandler;
+import org.glassfish.grizzly.http.server.HttpServer;
+import org.glassfish.grizzly.http.server.NetworkListener;
+import org.glassfish.grizzly.http.server.Request;
+import org.glassfish.grizzly.http.server.Response;
+import org.glassfish.grizzly.http.server.ServerConfiguration;
+import org.glassfish.grizzly.websockets.WebSocket;
+import org.glassfish.grizzly.websockets.WebSocketAddOn;
+import org.glassfish.grizzly.websockets.WebSocketApplication;
+import org.glassfish.grizzly.websockets.WebSocketEngine;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+final class JsonDynamicHTTP extends HttpHandler {
+    private static int resourcesCount;
+    private static List<Resource> resources;
+    private static ServerConfiguration conf;
+    private static HttpServer server;
+
+    private JsonDynamicHTTP() {
+    }
+
+    static URI initServer() throws Exception {
+        server = HttpServer.createSimpleServer(null, new PortRange(8080, 
65535));
+        final WebSocketAddOn addon = new WebSocketAddOn();
+        for (NetworkListener listener : server.getListeners()) {
+            listener.registerAddOn(addon);
+        }
+        resources = new ArrayList<Resource>();
+
+        conf = server.getServerConfiguration();
+        final JsonDynamicHTTP dh = new JsonDynamicHTTP();
+
+        conf.addHttpHandler(dh, "/");
+
+        server.start();
+
+        return pageURL("http", server, "/test.html");
+    }
+
+    @Override
+    public void service(Request request, Response response) throws Exception {
+        if ("/test.html".equals(request.getRequestURI())) {
+            response.setContentType("text/html");
+            final InputStream is = 
JsonDynamicHTTP.class.getResourceAsStream("test.html");
+            copyStream(is, response.getOutputStream(), null);
+            return;
+        }
+        if ("/dynamic".equals(request.getRequestURI())) {
+            String mimeType = request.getParameter("mimeType");
+            List<String> params = new ArrayList<String>();
+            boolean webSocket = false;
+            for (int i = 0;; i++) {
+                String p = request.getParameter("param" + i);
+                if (p == null) {
+                    break;
+                }
+                if ("protocol:ws".equals(p)) {
+                    webSocket = true;
+                    continue;
+                }
+                params.add(p);
+            }
+            final String cnt = request.getParameter("content");
+            String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
+            ByteArrayInputStream is = new 
ByteArrayInputStream(mangle.getBytes("UTF-8"));
+            URI url;
+            final Resource res = new Resource(is, mimeType, "/dynamic/res" + 
++resourcesCount, params.toArray(new String[params.size()]));
+            if (webSocket) {
+                url = registerWebSocket(res);
+            } else {
+                url = registerResource(res);
+            }
+            response.getWriter().write(url.toString());
+            response.getWriter().write("\n");
+            return;
+        }
+
+        for (Resource r : resources) {
+            if (r.httpPath.equals(request.getRequestURI())) {
+                response.setContentType(r.httpType);
+                r.httpContent.reset();
+                String[] params = null;
+                if (r.parameters.length != 0) {
+                    params = new String[r.parameters.length];
+                    for (int i = 0; i < r.parameters.length; i++) {
+                        params[i] = request.getParameter(r.parameters[i]);
+                        if (params[i] == null) {
+                            if ("http.method".equals(r.parameters[i])) {
+                                params[i] = request.getMethod().toString();
+                            } else if 
("http.requestBody".equals(r.parameters[i])) {
+                                Reader rdr = request.getReader();
+                                StringBuilder sb = new StringBuilder();
+                                for (;;) {
+                                    int ch = rdr.read();
+                                    if (ch == -1) {
+                                        break;
+                                    }
+                                    sb.append((char) ch);
+                                }
+                                params[i] = sb.toString();
+                            } else if 
(r.parameters[i].startsWith("http.header.")) {
+                                params[i] = 
request.getHeader(r.parameters[i].substring(12));
+                            }
+                        }
+                        if (params[i] == null) {
+                            params[i] = "null";
+                        }
+                    }
+                }
+
+                copyStream(r.httpContent, response.getOutputStream(), null, 
params);
+            }
+        }
+    }
+
+    private URI registerWebSocket(Resource r) {
+        WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
+        return pageURL("ws", server, r.httpPath);
+    }
+
+    private URI registerResource(Resource r) {
+        if (!resources.contains(r)) {
+            resources.add(r);
+            conf.addHttpHandler(this, r.httpPath);
+        }
+        return pageURL("http", server, r.httpPath);
+    }
+
+    private static URI pageURL(String proto, HttpServer server, final String 
page) {
+        NetworkListener listener = server.getListeners().iterator().next();
+        int port = listener.getPort();
+        try {
+            return new URI(proto + "://localhost:" + port + page);
+        } catch (URISyntaxException ex) {
+            throw new IllegalStateException(ex);
+        }
+    }
+
+    static final class Resource {
+
+        final InputStream httpContent;
+        final String httpType;
+        final String httpPath;
+        final String[] parameters;
+
+        Resource(InputStream httpContent, String httpType, String httpPath,
+            String[] parameters) {
+            httpContent.mark(Integer.MAX_VALUE);
+            this.httpContent = httpContent;
+            this.httpType = httpType;
+            this.httpPath = httpPath;
+            this.parameters = parameters;
+        }
+    }
+
+    static void copyStream(InputStream is, OutputStream os, String baseURL, 
String... params) throws IOException {
+        for (;;) {
+            int ch = is.read();
+            if (ch == -1) {
+                break;
+            }
+            if (ch == '$' && params.length > 0) {
+                int cnt = is.read() - '0';
+                if (baseURL != null && cnt == 'U' - '0') {
+                    os.write(baseURL.getBytes("UTF-8"));
+                } else {
+                    if (cnt >= 0 && cnt < params.length) {
+                        os.write(params[cnt].getBytes("UTF-8"));
+                    } else {
+                        os.write('$');
+                        os.write(cnt + '0');
+                    }
+                }
+            } else {
+                os.write(ch);
+            }
+        }
+    }
+
+    private static class WS extends WebSocketApplication {
+        private final Resource r;
+
+        private WS(Resource r) {
+            this.r = r;
+        }
+
+        @Override
+        public void onMessage(WebSocket socket, String text) {
+            try {
+                r.httpContent.reset();
+                ByteArrayOutputStream out = new ByteArrayOutputStream();
+                copyStream(r.httpContent, out, null, text);
+                String s = new String(out.toByteArray(), "UTF-8");
+                socket.send(s);
+            } catch (IOException ex) {
+                LOG.log(Level.WARNING, null, ex);
+            }
+        }
+        private static final Logger LOG = Logger.getLogger(WS.class.getName());
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/xhr4j/src/test/java/org/netbeans/html/xhr4j/JsonFX.java
----------------------------------------------------------------------
diff --git a/xhr4j/src/test/java/org/netbeans/html/xhr4j/JsonFX.java 
b/xhr4j/src/test/java/org/netbeans/html/xhr4j/JsonFX.java
new file mode 100644
index 0000000..5b301e2
--- /dev/null
+++ b/xhr4j/src/test/java/org/netbeans/html/xhr4j/JsonFX.java
@@ -0,0 +1,125 @@
+/**
+ * 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.xhr4j;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import javafx.application.Platform;
+import org.netbeans.html.boot.impl.FnContext;
+import org.netbeans.html.boot.spi.Fn;
+import org.testng.ITest;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public final class JsonFX implements ITest, Runnable {
+    private final Fn.Presenter p;
+    private final Method m;
+    private Object result;
+    private Object inst;
+    private int count;
+
+    JsonFX(Fn.Presenter p, Method m) {
+        this.p = p;
+        this.m = m;
+    }
+
+    @Override
+    public String getTestName() {
+        return m.getName();
+    }
+
+    @Test
+    public synchronized void executeTest() throws Exception {
+        if (result == null) {
+            Platform.runLater(this);
+            wait();
+        }
+        if (result instanceof Exception) {
+            throw (Exception)result;
+        }
+        if (result instanceof Error) {
+            throw (Error)result;
+        }
+    }
+
+    @Override
+    public synchronized void run() {
+        boolean notify = true;
+        try {
+            FnContext.currentPresenter(p);
+            if (inst == null) {
+                inst = m.getDeclaringClass().newInstance();
+            }
+            result = m.invoke(inst);
+            if (result == null) {
+                result = this;
+            }
+        } catch (InvocationTargetException ex) {
+            Throwable r = ex.getTargetException();
+            if (r instanceof InterruptedException) {
+                if (count++ < 100) {
+                    notify = false;
+                    try {
+                        Thread.sleep(100);
+                    } catch (Exception ex1) {
+                        // ignore and continue
+                    }
+                    Platform.runLater(this);
+                    return;
+                }
+            }
+            result = r;
+        } catch (Exception ex) {
+            result = ex;
+        } finally {
+            if (notify) {
+                notifyAll();
+            }
+            FnContext.currentPresenter(null);
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/xhr4j/src/test/java/org/netbeans/html/xhr4j/JsonKnockoutTest.java
----------------------------------------------------------------------
diff --git a/xhr4j/src/test/java/org/netbeans/html/xhr4j/JsonKnockoutTest.java 
b/xhr4j/src/test/java/org/netbeans/html/xhr4j/JsonKnockoutTest.java
new file mode 100644
index 0000000..b84be22
--- /dev/null
+++ b/xhr4j/src/test/java/org/netbeans/html/xhr4j/JsonKnockoutTest.java
@@ -0,0 +1,217 @@
+/**
+ * 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.xhr4j;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import net.java.html.BrwsrCtx;
+import net.java.html.boot.BrowserBuilder;
+import net.java.html.js.JavaScriptBody;
+import org.netbeans.html.boot.spi.Fn;
+import org.netbeans.html.context.spi.Contexts;
+import org.netbeans.html.json.spi.Technology;
+import org.netbeans.html.json.tck.KOTest;
+import org.netbeans.html.json.tck.KnockoutTCK;
+import org.netbeans.html.ko4j.KO4J;
+import org.openide.util.lookup.ServiceProvider;
+import org.testng.Assert;
+import static org.testng.Assert.*;
+import org.testng.annotations.Factory;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+@ServiceProvider(service = KnockoutTCK.class)
+public final class JsonKnockoutTest extends KnockoutTCK {
+    private static Class<?> browserClass;
+    private static Fn.Presenter browserContext;
+    
+    public JsonKnockoutTest() {
+    }
+    
+    @Factory public static Object[] compatibilityTests() throws Exception {
+        Class[] arr = testClasses();
+        for (int i = 0; i < arr.length; i++) {
+            assertEquals(arr[i].getClassLoader(),
+                JsonKnockoutTest.class.getClassLoader(),
+                "All classes loaded by the same classloader"
+            );
+        }
+        
+        URI uri = JsonDynamicHTTP.initServer();
+    
+        final BrowserBuilder bb = 
BrowserBuilder.newBrowser().loadClass(JsonKnockoutTest.class).
+            loadPage(uri.toString()).
+            invoke("initialized");
+        
+        Executors.newSingleThreadExecutor().submit(new Runnable() {
+            @Override
+            public void run() {
+                bb.showAndWait();
+            }
+        });
+        
+        ClassLoader l = getClassLoader();
+        List<Object> res = new ArrayList<Object>();
+        for (int i = 0; i < arr.length; i++) {
+            Class<?> c = Class.forName(arr[i].getName(), true, l);
+            Class<? extends Annotation> koTest = 
+                c.getClassLoader().loadClass(KOTest.class.getName()).
+                asSubclass(Annotation.class);
+            for (Method m : c.getMethods()) {
+                if (m.getAnnotation(koTest) != null) {
+                    res.add(new JsonFX(browserContext, m));
+                }
+            }
+        }
+        return res.toArray();
+    }
+
+    static synchronized ClassLoader getClassLoader() throws 
InterruptedException {
+        while (browserClass == null) {
+            JsonKnockoutTest.class.wait();
+        }
+        return browserClass.getClassLoader();
+    }
+    
+    public static synchronized void initialized(Class<?> browserCls) throws 
Exception {
+        browserClass = browserCls;
+        browserContext = Fn.activePresenter();
+        JsonKnockoutTest.class.notifyAll();
+    }
+    
+    public static void initialized() throws Exception {
+        Assert.assertSame(JsonKnockoutTest.class.getClassLoader(),
+            ClassLoader.getSystemClassLoader(),
+            "No special classloaders"
+        );
+        JsonKnockoutTest.initialized(JsonKnockoutTest.class);
+    }
+
+    @Override
+    public boolean canFailWebSocketTest() {
+        return true;
+    }
+    
+    @Override
+    public BrwsrCtx createContext() {
+        KO4J ko = new KO4J(browserContext);
+        XmlHttpResourceContext tc = new XmlHttpResourceContext();
+        Contexts.Builder cb = Contexts.newBuilder().
+            register(Technology.class, ko.knockout(), 10).
+            register(Executor.class, (Executor)browserContext, 10).
+            register(Fn.Presenter.class, (Fn.Presenter)browserContext, 10);
+        tc.fillContext(cb, browserClass);
+        return cb.build();
+    }
+
+    @Override
+    public Object createJSON(Map<String, Object> values) {
+        Object json = createJSON();
+        for (Map.Entry<String, Object> entry : values.entrySet()) {
+            setProperty(json, entry.getKey(), entry.getValue());
+        }
+        return json;
+    }
+
+    @JavaScriptBody(args = {}, body = "return new Object();")
+    private static native Object createJSON();
+
+    @JavaScriptBody(args = {"json", "key", "value"}, body = "json[key] = 
value;")
+    private static native void setProperty(Object json, String key, Object 
value);
+
+    @Override
+    @JavaScriptBody(args = { "s", "args" }, body = ""
+        + "var f = new Function(s); "
+        + "return f.apply(null, args);"
+    )
+    public native Object executeScript(String script, Object[] arguments);
+
+    @JavaScriptBody(args = {  }, body = 
+          "var h;"
+        + "if (!!window && !!window.location && !!window.location.href)\n"
+        + "  h = window.location.href;\n"
+        + "else "
+        + "  h = null;"
+        + "return h;\n"
+    )
+    private static native String findBaseURL();
+    
+    @Override
+    public URI prepareURL(String content, String mimeType, String[] 
parameters) {
+        try {
+            final URL baseURL = new URL(findBaseURL());
+            StringBuilder sb = new StringBuilder();
+            sb.append("/dynamic?mimeType=").append(mimeType);
+            for (int i = 0; i < parameters.length; i++) {
+                sb.append("&param" + i).append("=").append(parameters[i]);
+            }
+            String mangle = content.replace("\n", "%0a")
+                .replace("\"", "\\\"").replace(" ", "%20");
+            sb.append("&content=").append(mangle);
+
+            URL query = new URL(baseURL, sb.toString());
+            URLConnection c = query.openConnection();
+            BufferedReader br = new BufferedReader(new 
InputStreamReader(c.getInputStream()));
+            URI connectTo = new URI(br.readLine());
+            return connectTo;
+        } catch (IOException ex) {
+            throw new IllegalStateException(ex);
+        } catch (URISyntaxException ex) {
+            throw new IllegalStateException(ex);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/xhr4j/src/test/resources/org/netbeans/html/xhr4j/test.html
----------------------------------------------------------------------
diff --git a/xhr4j/src/test/resources/org/netbeans/html/xhr4j/test.html 
b/xhr4j/src/test/resources/org/netbeans/html/xhr4j/test.html
new file mode 100644
index 0000000..3951417
--- /dev/null
+++ b/xhr4j/src/test/resources/org/netbeans/html/xhr4j/test.html
@@ -0,0 +1,56 @@
+<!--
+
+    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+    Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+
+    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+    Other names may be trademarks of their respective owners.
+
+    The contents of this file are subject to the terms of either the GNU
+    General Public License Version 2 only ("GPL") or the Common
+    Development and Distribution License("CDDL") (collectively, the
+    "License"). You may not use this file except in compliance with the
+    License. You can obtain a copy of the License at
+    http://www.netbeans.org/cddl-gplv2.html
+    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+    specific language governing permissions and limitations under the
+    License.  When distributing the software, include this License Header
+    Notice in each file and include the License file at
+    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+    particular file as subject to the "Classpath" exception as provided
+    by Oracle in the GPL Version 2 section of the License file that
+    accompanied this code. If applicable, add the following below the
+    License Header, with the fields enclosed by brackets [] replaced by
+    your own identifying information:
+    "Portions Copyrighted [year] [name of copyright owner]"
+
+    Contributor(s):
+
+    The Original Software is NetBeans. The Initial Developer of the Original
+    Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights 
Reserved.
+
+    If you wish your version of this file to be governed by only the CDDL
+    or only the GPL Version 2, indicate your decision by adding
+    "[Contributor] elects to include this software in this distribution
+    under the [CDDL or GPL Version 2] license." If you do not indicate a
+    single choice of license, a recipient has the option to distribute
+    your version of this file under either the CDDL, the GPL Version 2 or
+    to extend the choice of license to its licensees as provided above.
+    However, if you add GPL Version 2 code and therefore, elected the GPL
+    Version 2 license, then the option applies only if the new code is
+    made subject to such option by the copyright holder.
+
+-->
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>XHR via Java Harness</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+        <meta name="viewport" content="width=device-width">
+    </head>
+    <body>
+        <h1>XHR via Java Harness</h1>
+    </body>
+    <script></script>
+</html>

Reply via email to