Referencing most recent version 1.2.3
authorJaroslav Tulach <jtulach@netbeans.org>
Mon, 29 Feb 2016 05:39:42 +0100
changeset 1059c5223a12e761
parent 1058 3554078c32ce
parent 1057 b547f8f663f5
child 1060 b594c4ab82f3
Referencing most recent version 1.2.3
pom.xml
src/main/javadoc/overview.html
xhr4j/pom.xml
xhr4j/src/main/java/org/netbeans/html/xhr4j/LoadJSON.java
xhr4j/src/test/java/org/netbeans/html/xhr4j/JsonFX.java
     1.1 --- a/context/src/main/java/org/netbeans/html/context/spi/Contexts.java	Mon Feb 29 05:33:31 2016 +0100
     1.2 +++ b/context/src/main/java/org/netbeans/html/context/spi/Contexts.java	Mon Feb 29 05:39:42 2016 +0100
     1.3 @@ -42,6 +42,7 @@
     1.4   */
     1.5  package org.netbeans.html.context.spi;
     1.6  
     1.7 +import java.lang.annotation.Documented;
     1.8  import java.lang.annotation.ElementType;
     1.9  import java.lang.annotation.Retention;
    1.10  import java.lang.annotation.RetentionPolicy;
    1.11 @@ -159,6 +160,7 @@
    1.12       */
    1.13      @Retention(RetentionPolicy.RUNTIME)
    1.14      @Target(ElementType.TYPE)
    1.15 +    @Documented
    1.16      public @interface Id {
    1.17          /** Identifier(s) for the implementation. 
    1.18           * 
     2.1 --- a/json/src/main/java/org/netbeans/html/json/impl/RcvrJSON.java	Mon Feb 29 05:33:31 2016 +0100
     2.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/RcvrJSON.java	Mon Feb 29 05:39:42 2016 +0100
     2.3 @@ -42,8 +42,7 @@
     2.4   */
     2.5  package org.netbeans.html.json.impl;
     2.6  
     2.7 -import java.util.ArrayList;
     2.8 -import net.java.html.BrwsrCtx;
     2.9 +import java.util.concurrent.Callable;
    2.10  
    2.11  /** Super type for those who wish to receive JSON messages.
    2.12   *
    2.13 @@ -94,11 +93,20 @@
    2.14              };
    2.15          }
    2.16          
    2.17 -        public static MsgEvnt createMessage(final Object value) {
    2.18 +         public static MsgEvnt createMessage(final Object value) {
    2.19              return new MsgEvnt() {
    2.20 +                private Object val = value;
    2.21 +
    2.22                  @Override
    2.23                  public Object[] getValues() {
    2.24 -                    return value instanceof Object[] ? (Object[])value : new Object[] { value };
    2.25 +                    if (val instanceof Callable) {
    2.26 +                        try {
    2.27 +                            val = ((Callable)val).call();
    2.28 +                        } catch (Exception ex) {
    2.29 +                            throw new IllegalStateException("Cannot compute " + val, ex);
    2.30 +                        }
    2.31 +                    }
    2.32 +                    return val instanceof Object[] ? (Object[])val : new Object[] { val };
    2.33                  }
    2.34                  
    2.35                  @Override
     3.1 --- a/pom.xml	Mon Feb 29 05:33:31 2016 +0100
     3.2 +++ b/pom.xml	Mon Feb 29 05:39:42 2016 +0100
     3.3 @@ -36,6 +36,7 @@
     3.4      <module>equinox-agentclass-hook</module>
     3.5      <module>boot-script</module>
     3.6      <module>boot-agent-test</module>
     3.7 +    <module>xhr4j</module>
     3.8    </modules>
     3.9    <licenses>
    3.10        <license>
    3.11 @@ -123,7 +124,7 @@
    3.12                    <subpackages>${publicPackages}</subpackages>
    3.13                    <skip>false</skip>
    3.14                    <excludePackageNames>
    3.15 -org.netbeans.html.boot.impl:org.netbeans.html.boot.fx:org.netbeans.html.context.impl:org.netbeans.html.equinox.*:org.netbeans.html.geo.impl:org.netbeans.html.json.impl:org.netbeans.html.sound.impl:org.netbeans.html.ko.*:org.netbeans.html.ko4j:org.netbeans.html.mojo:org.netbeans.html.wstyrus:net.java.html.js.tests:net.java.html.json.tests
    3.16 +org.netbeans.html.boot.impl:org.netbeans.html.boot.fx:org.netbeans.html.context.impl:org.netbeans.html.equinox.*:org.netbeans.html.geo.impl:org.netbeans.html.json.impl:org.netbeans.html.sound.impl:org.netbeans.html.ko.*:org.netbeans.html.ko4j:org.netbeans.html.mojo:org.netbeans.html.wstyrus:net.java.html.js.tests:net.java.html.json.tests:org.netbeans.html.xhr4j
    3.17                    </excludePackageNames>
    3.18                  <groups>
    3.19                    <group>
     4.1 --- a/src/main/javadoc/overview.html	Mon Feb 29 05:33:31 2016 +0100
     4.2 +++ b/src/main/javadoc/overview.html	Mon Feb 29 05:39:42 2016 +0100
     4.3 @@ -575,6 +575,7 @@
     4.4          online:
     4.5          <ul>
     4.6              <li>Current <a target="_blank" href="http://bits.netbeans.org/html+java/dev/">development</a> version
     4.7 +            <li>Version <a target="_blank" href="http://bits.netbeans.org/html+java/1.2.3">1.2.3</a>
     4.8              <li>Version <a target="_blank" href="http://bits.netbeans.org/html+java/1.1">1.1</a>
     4.9              <li>Version <a target="_blank" href="http://bits.netbeans.org/html+java/1.0">1.0</a>
    4.10              <li>Version <a target="_blank" href="http://bits.netbeans.org/html+java/0.9">0.9</a>
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/xhr4j/pom.xml	Mon Feb 29 05:39:42 2016 +0100
     5.3 @@ -0,0 +1,122 @@
     5.4 +<?xml version="1.0"?>
     5.5 +<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">
     5.6 +  <modelVersion>4.0.0</modelVersion>
     5.7 +  <parent>
     5.8 +    <groupId>org.netbeans.html</groupId>
     5.9 +    <artifactId>pom</artifactId>
    5.10 +    <version>2.0-SNAPSHOT</version>
    5.11 +  </parent>
    5.12 +  <groupId>org.netbeans.html</groupId>
    5.13 +  <artifactId>xhr4j</artifactId>
    5.14 +  <version>2.0-SNAPSHOT</version>
    5.15 +  <packaging>bundle</packaging>
    5.16 +  <name>XHR via Java</name>
    5.17 +  <url>http://maven.apache.org</url>
    5.18 +    <build>
    5.19 +        <plugins>
    5.20 +            <plugin>
    5.21 +                <groupId>org.apache.felix</groupId>
    5.22 +                <artifactId>maven-bundle-plugin</artifactId>
    5.23 +            </plugin>
    5.24 +            <plugin>
    5.25 +                <groupId>org.netbeans.html</groupId>
    5.26 +                <artifactId>html4j-maven-plugin</artifactId>
    5.27 +            </plugin>
    5.28 +            <plugin>
    5.29 +                <groupId>org.apache.maven.plugins</groupId>
    5.30 +                <artifactId>maven-javadoc-plugin</artifactId>
    5.31 +                <configuration>
    5.32 +                    <skip>false</skip>
    5.33 +                </configuration>
    5.34 +            </plugin>
    5.35 +        </plugins>
    5.36 +    </build>
    5.37 +    <properties>
    5.38 +    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    5.39 +    <bundleSymbolicName>org.netbeans.html.xhr4j</bundleSymbolicName>
    5.40 +  </properties>
    5.41 +  <dependencies>
    5.42 +    <!-- compile only deps -->
    5.43 +    <dependency>
    5.44 +      <groupId>org.netbeans.api</groupId>
    5.45 +      <artifactId>org-openide-util-lookup</artifactId>
    5.46 +      <type>jar</type>
    5.47 +      <scope>provided</scope>
    5.48 +    </dependency>
    5.49 +
    5.50 +    <!-- compile + runtime -->      
    5.51 +    <dependency>
    5.52 +      <groupId>${project.groupId}</groupId>
    5.53 +      <artifactId>net.java.html</artifactId>
    5.54 +      <version>${project.version}</version>
    5.55 +      <type>jar</type>
    5.56 +    </dependency>
    5.57 +    <dependency>
    5.58 +      <groupId>${project.groupId}</groupId>
    5.59 +      <artifactId>net.java.html.json</artifactId>
    5.60 +      <version>${project.version}</version>
    5.61 +      <type>jar</type>
    5.62 +    </dependency>
    5.63 +    <!-- test only deps -->
    5.64 +    <dependency>
    5.65 +      <groupId>${project.groupId}</groupId>
    5.66 +      <artifactId>net.java.html.boot</artifactId>
    5.67 +      <version>${project.version}</version>
    5.68 +      <scope>provided</scope>
    5.69 +      <type>jar</type>
    5.70 +    </dependency>
    5.71 +    <dependency>
    5.72 +      <groupId>${project.groupId}</groupId>
    5.73 +      <artifactId>net.java.html.json.tck</artifactId>
    5.74 +      <version>${project.version}</version>
    5.75 +      <scope>test</scope>
    5.76 +      <type>jar</type>
    5.77 +    </dependency>
    5.78 +    <dependency>
    5.79 +      <groupId>${project.groupId}</groupId>
    5.80 +      <artifactId>ko4j</artifactId>
    5.81 +      <version>${project.version}</version>
    5.82 +      <scope>test</scope>
    5.83 +      <type>jar</type>
    5.84 +    </dependency>
    5.85 +    <dependency>
    5.86 +      <groupId>org.glassfish.grizzly</groupId>
    5.87 +      <artifactId>grizzly-http-server-core</artifactId>
    5.88 +      <version>${grizzly.version}</version>
    5.89 +      <scope>test</scope>
    5.90 +      <type>jar</type>
    5.91 +    </dependency>
    5.92 +    <dependency>
    5.93 +      <groupId>org.glassfish.grizzly</groupId>
    5.94 +      <artifactId>grizzly-websockets-server</artifactId>
    5.95 +      <version>${grizzly.version}</version>
    5.96 +      <scope>test</scope>
    5.97 +      <type>jar</type>
    5.98 +    </dependency>
    5.99 +    <dependency>
   5.100 +        <groupId>${project.groupId}</groupId>
   5.101 +        <artifactId>net.java.html.boot.fx</artifactId>
   5.102 +        <version>${project.version}</version>
   5.103 +        <scope>test</scope>
   5.104 +    </dependency>
   5.105 +    <dependency>
   5.106 +      <groupId>org.glassfish.grizzly</groupId>
   5.107 +      <artifactId>grizzly-http-server</artifactId>
   5.108 +      <version>${grizzly.version}</version>
   5.109 +      <scope>test</scope>
   5.110 +    </dependency>
   5.111 +    <dependency>
   5.112 +        <groupId>org.glassfish.grizzly</groupId>
   5.113 +        <artifactId>grizzly-http-servlet</artifactId>
   5.114 +        <version>${grizzly.version}</version>
   5.115 +        <scope>test</scope>
   5.116 +    </dependency>    
   5.117 +    <dependency>
   5.118 +        <groupId>javax.servlet</groupId>
   5.119 +        <artifactId>javax.servlet-api</artifactId>
   5.120 +        <scope>test</scope>
   5.121 +    </dependency>
   5.122 +  </dependencies>
   5.123 +    <description>Implementation module with support for XHR via Java.
   5.124 +Use it to workaround CORS limitations.</description>
   5.125 +</project>
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/xhr4j/src/main/java/org/netbeans/html/xhr4j/LoadJSON.java	Mon Feb 29 05:39:42 2016 +0100
     6.3 @@ -0,0 +1,274 @@
     6.4 +/**
     6.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     6.6 + *
     6.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
     6.8 + *
     6.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    6.10 + * Other names may be trademarks of their respective owners.
    6.11 + *
    6.12 + * The contents of this file are subject to the terms of either the GNU
    6.13 + * General Public License Version 2 only ("GPL") or the Common
    6.14 + * Development and Distribution License("CDDL") (collectively, the
    6.15 + * "License"). You may not use this file except in compliance with the
    6.16 + * License. You can obtain a copy of the License at
    6.17 + * http://www.netbeans.org/cddl-gplv2.html
    6.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    6.19 + * specific language governing permissions and limitations under the
    6.20 + * License.  When distributing the software, include this License Header
    6.21 + * Notice in each file and include the License file at
    6.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    6.23 + * particular file as subject to the "Classpath" exception as provided
    6.24 + * by Oracle in the GPL Version 2 section of the License file that
    6.25 + * accompanied this code. If applicable, add the following below the
    6.26 + * License Header, with the fields enclosed by brackets [] replaced by
    6.27 + * your own identifying information:
    6.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    6.29 + *
    6.30 + * Contributor(s):
    6.31 + *
    6.32 + * The Original Software is NetBeans. The Initial Developer of the Original
    6.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
    6.34 + *
    6.35 + * If you wish your version of this file to be governed by only the CDDL
    6.36 + * or only the GPL Version 2, indicate your decision by adding
    6.37 + * "[Contributor] elects to include this software in this distribution
    6.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    6.39 + * single choice of license, a recipient has the option to distribute
    6.40 + * your version of this file under either the CDDL, the GPL Version 2 or
    6.41 + * to extend the choice of license to its licensees as provided above.
    6.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    6.43 + * Version 2 license, then the option applies only if the new code is
    6.44 + * made subject to such option by the copyright holder.
    6.45 + */
    6.46 +package org.netbeans.html.xhr4j;
    6.47 +
    6.48 +import java.io.IOException;
    6.49 +import java.io.InputStream;
    6.50 +import java.io.InputStreamReader;
    6.51 +import java.io.OutputStream;
    6.52 +import java.io.PushbackInputStream;
    6.53 +import java.io.Reader;
    6.54 +import java.io.UnsupportedEncodingException;
    6.55 +import java.net.HttpURLConnection;
    6.56 +import java.net.URL;
    6.57 +import java.net.URLConnection;
    6.58 +import java.util.concurrent.Callable;
    6.59 +import java.util.concurrent.Executor;
    6.60 +import java.util.concurrent.Executors;
    6.61 +import java.util.concurrent.ThreadFactory;
    6.62 +import java.util.logging.Logger;
    6.63 +import net.java.html.js.JavaScriptBody;
    6.64 +import org.netbeans.html.json.spi.JSONCall;
    6.65 +
    6.66 +/** This is an implementation package - just
    6.67 + * include its JAR on classpath and use official {@link Context} API
    6.68 + * to access the functionality.
    6.69 + *
    6.70 + * @author Jaroslav Tulach
    6.71 + */
    6.72 +final class LoadJSON implements Runnable {
    6.73 +    private static final Logger LOG = Logger.getLogger(LoadJSON.class.getName());
    6.74 +    private static final Executor REQ = Executors.newCachedThreadPool(new ThreadFactory() {
    6.75 +        @Override
    6.76 +        public Thread newThread(Runnable runnable) {
    6.77 +            Thread thread = Executors.defaultThreadFactory().newThread(runnable);
    6.78 +            thread.setDaemon(true);
    6.79 +            thread.setName("xhr4j daemon");
    6.80 +            return thread;
    6.81 +        }
    6.82 +    });
    6.83 +
    6.84 +    private final JSONCall call;
    6.85 +    private final URL base;
    6.86 +
    6.87 +
    6.88 +    private LoadJSON(JSONCall call) {
    6.89 +        this.call = call;
    6.90 +        this.base = null;
    6.91 +    }
    6.92 +
    6.93 +    public static void loadJSON(JSONCall call) {
    6.94 +        assert !"WebSocket".equals(call.getMethod());
    6.95 +        REQ.execute(new LoadJSON((call)));
    6.96 +    }
    6.97 +
    6.98 +    @Override
    6.99 +    public void run() {
   6.100 +        final String url;
   6.101 +        Throwable error = null;
   6.102 +        Object json = null;
   6.103 +
   6.104 +        if (call.isJSONP()) {
   6.105 +            url = call.composeURL("dummy");
   6.106 +        } else {
   6.107 +            url = call.composeURL(null);
   6.108 +        }
   6.109 +        try {
   6.110 +            final URL u = new URL(base, url.replace(" ", "%20"));
   6.111 +            URLConnection conn = u.openConnection();
   6.112 +            if (call.isDoOutput()) {
   6.113 +                conn.setDoOutput(true);
   6.114 +            }
   6.115 +            String h = call.getHeaders();
   6.116 +            if (h != null) {
   6.117 +                int pos = 0;
   6.118 +                while (pos < h.length()) {
   6.119 +                    int tagEnd = h.indexOf(':', pos);
   6.120 +                    if (tagEnd == -1) {
   6.121 +                        break;
   6.122 +                    }
   6.123 +                    int r = h.indexOf('\r', tagEnd);
   6.124 +                    int n = h.indexOf('\n', tagEnd);
   6.125 +                    if (r == -1) {
   6.126 +                        r = h.length();
   6.127 +                    }
   6.128 +                    if (n == -1) {
   6.129 +                        n = h.length();
   6.130 +                    }
   6.131 +                    String key = h.substring(pos, tagEnd).trim();
   6.132 +                    String val = h.substring(tagEnd + 1, Math.min(r, n)).trim();
   6.133 +                    conn.setRequestProperty(key, val);;
   6.134 +                    pos = Math.max(r, n);
   6.135 +                }
   6.136 +            }
   6.137 +            if (call.getMethod() != null && conn instanceof HttpURLConnection) {
   6.138 +                ((HttpURLConnection) conn).setRequestMethod(call.getMethod());
   6.139 +            }
   6.140 +            if (call.isDoOutput()) {
   6.141 +                final OutputStream os = conn.getOutputStream();
   6.142 +                call.writeData(os);
   6.143 +                os.flush();
   6.144 +            }
   6.145 +            final PushbackInputStream is = new PushbackInputStream(
   6.146 +                conn.getInputStream(), 1
   6.147 +            );
   6.148 +            boolean[] arrayOrString = { false, false };
   6.149 +            detectJSONType(call.isJSONP(), is, arrayOrString);
   6.150 +            String response = readStream(is);
   6.151 +            if (call.isJSONP()) {
   6.152 +                response = '(' + response;
   6.153 +            }
   6.154 +            json = new Result(response, arrayOrString[0], arrayOrString[1]);
   6.155 +        } catch (IOException ex) {
   6.156 +            error = ex;
   6.157 +        } finally {
   6.158 +            if (error != null) {
   6.159 +                call.notifyError(error);
   6.160 +            } else {
   6.161 +                call.notifySuccess(json);
   6.162 +            }
   6.163 +        }
   6.164 +    }
   6.165 +
   6.166 +    private static final class Result implements Callable<Object> {
   6.167 +        private final String response;
   6.168 +        private final boolean array;
   6.169 +        private final boolean plain;
   6.170 +
   6.171 +        Result(String response, boolean array, boolean plain) {
   6.172 +            this.response = response;
   6.173 +            this.array = array;
   6.174 +            this.plain = plain;
   6.175 +        }
   6.176 +
   6.177 +        @Override
   6.178 +        public Object call() throws Exception {
   6.179 +            if (plain) {
   6.180 +                return response;
   6.181 +            } else {
   6.182 +                if (array) {
   6.183 +                    Object r = parse(response);
   6.184 +                    Object[] arr = r instanceof Object[] ? (Object[])r : new Object[] { r };
   6.185 +                    for (int i = 0; i < arr.length; i++) {
   6.186 +                        arr[i] = new JSObjToStr(response, arr[i]);
   6.187 +                    }
   6.188 +                    return arr;
   6.189 +                } else {
   6.190 +                    return new JSObjToStr(response, parse(response));
   6.191 +                }
   6.192 +            }
   6.193 +        }
   6.194 +    }
   6.195 +    private static final class JSObjToStr {
   6.196 +        final String str;
   6.197 +        final Object obj;
   6.198 +
   6.199 +        public JSObjToStr(Object str, Object obj) {
   6.200 +            this.str = str == null ? "" : str.toString();
   6.201 +            this.obj = obj;
   6.202 +        }
   6.203 +
   6.204 +        @Override
   6.205 +        public String toString() {
   6.206 +            return str;
   6.207 +        }
   6.208 +    }
   6.209 +
   6.210 +    static String readStream(InputStream is) throws IOException, UnsupportedEncodingException {
   6.211 +        Reader r = new InputStreamReader(is, "UTF-8");
   6.212 +        StringBuilder sb = new StringBuilder();
   6.213 +        char[] arr = new char[4096];
   6.214 +        for (;;) {
   6.215 +            int len = r.read(arr);
   6.216 +            if (len == -1) {
   6.217 +                break;
   6.218 +            }
   6.219 +            sb.append(arr, 0, len);
   6.220 +        }
   6.221 +        return sb.toString();
   6.222 +    }
   6.223 +
   6.224 +    private static void detectJSONType(boolean skipAnything, final PushbackInputStream is, boolean[] arrayOrString) throws IOException {
   6.225 +        for (;;) {
   6.226 +            int ch = is.read();
   6.227 +            if (ch == -1) {
   6.228 +                arrayOrString[1] = true;
   6.229 +                break;
   6.230 +            }
   6.231 +            if (Character.isWhitespace(ch)) {
   6.232 +                continue;
   6.233 +            }
   6.234 +
   6.235 +            if (ch == '[') {
   6.236 +                is.unread(ch);
   6.237 +                arrayOrString[0] = true;
   6.238 +                break;
   6.239 +            }
   6.240 +            if (ch == '{') {
   6.241 +                is.unread(ch);
   6.242 +                break;
   6.243 +            }
   6.244 +            if (!skipAnything) {
   6.245 +                is.unread(ch);
   6.246 +                arrayOrString[1] = true;
   6.247 +                break;
   6.248 +            }
   6.249 +        }
   6.250 +    }
   6.251 +
   6.252 +    @JavaScriptBody(args = {"object", "property"}, body =
   6.253 +        "var ret;\n" + 
   6.254 +        "if (property === null) ret = object;\n" + 
   6.255 +        "else if (object === null) ret = null;\n" + 
   6.256 +        "else ret = object[property];\n" + 
   6.257 +        "return ret ? (typeof ko === 'undefined' ? ret : ko.utils.unwrapObservable(ret)) : null;"
   6.258 +    )
   6.259 +    private static Object getProperty(Object object, String property) {
   6.260 +        return null;
   6.261 +    }
   6.262 +
   6.263 +    @JavaScriptBody(args = {"s"}, body = "return eval('(' + s + ')');")
   6.264 +    static Object parse(String s) {
   6.265 +        throw new IllegalStateException("No parser context for " + s);
   6.266 +    }
   6.267 +
   6.268 +    static void extractJSON(Object js, String[] props, Object[] values) {
   6.269 +        if (js instanceof JSObjToStr) {
   6.270 +            js = ((JSObjToStr)js).obj;
   6.271 +        }
   6.272 +        for (int i = 0; i < props.length; i++) {
   6.273 +            values[i] = getProperty(js, props[i]);
   6.274 +        }
   6.275 +    }
   6.276 +
   6.277 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/xhr4j/src/main/java/org/netbeans/html/xhr4j/XmlHttpResourceContext.java	Mon Feb 29 05:39:42 2016 +0100
     7.3 @@ -0,0 +1,88 @@
     7.4 +/**
     7.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     7.6 + *
     7.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
     7.8 + *
     7.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    7.10 + * Other names may be trademarks of their respective owners.
    7.11 + *
    7.12 + * The contents of this file are subject to the terms of either the GNU
    7.13 + * General Public License Version 2 only ("GPL") or the Common
    7.14 + * Development and Distribution License("CDDL") (collectively, the
    7.15 + * "License"). You may not use this file except in compliance with the
    7.16 + * License. You can obtain a copy of the License at
    7.17 + * http://www.netbeans.org/cddl-gplv2.html
    7.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    7.19 + * specific language governing permissions and limitations under the
    7.20 + * License.  When distributing the software, include this License Header
    7.21 + * Notice in each file and include the License file at
    7.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    7.23 + * particular file as subject to the "Classpath" exception as provided
    7.24 + * by Oracle in the GPL Version 2 section of the License file that
    7.25 + * accompanied this code. If applicable, add the following below the
    7.26 + * License Header, with the fields enclosed by brackets [] replaced by
    7.27 + * your own identifying information:
    7.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    7.29 + *
    7.30 + * Contributor(s):
    7.31 + *
    7.32 + * The Original Software is NetBeans. The Initial Developer of the Original
    7.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
    7.34 + *
    7.35 + * If you wish your version of this file to be governed by only the CDDL
    7.36 + * or only the GPL Version 2, indicate your decision by adding
    7.37 + * "[Contributor] elects to include this software in this distribution
    7.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    7.39 + * single choice of license, a recipient has the option to distribute
    7.40 + * your version of this file under either the CDDL, the GPL Version 2 or
    7.41 + * to extend the choice of license to its licensees as provided above.
    7.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    7.43 + * Version 2 license, then the option applies only if the new code is
    7.44 + * made subject to such option by the copyright holder.
    7.45 + */
    7.46 +package org.netbeans.html.xhr4j;
    7.47 +
    7.48 +import java.io.IOException;
    7.49 +import java.io.InputStream;
    7.50 +import net.java.html.json.OnReceive;
    7.51 +import org.netbeans.html.context.spi.Contexts;
    7.52 +import org.netbeans.html.json.spi.JSONCall;
    7.53 +import org.netbeans.html.json.spi.Transfer;
    7.54 +import org.openide.util.lookup.ServiceProvider;
    7.55 +
    7.56 +/** Implementation module with support for XHR via Java.
    7.57 + * Handles {@link OnReceive} requests by using Java to connect to given
    7.58 + * URL and then parsing it via JavaScript. Use this module if you have
    7.59 + * problems with CORS - as the Java connection isn't restricted by CORS
    7.60 + * rules.
    7.61 + * 
    7.62 + * Registers {@link Transfer} technology at position <code>50</code>.
    7.63 + * The {@link Contexts.Id} of the technology is <b>xhr4j</b>.
    7.64 + * 
    7.65 + * @author Jaroslav Tulach
    7.66 + * @since 1.3
    7.67 + */
    7.68 +@Contexts.Id("xhr4j")
    7.69 +@ServiceProvider(service = Contexts.Provider.class)
    7.70 +public final class XmlHttpResourceContext
    7.71 +implements Contexts.Provider, Transfer {
    7.72 +    @Override
    7.73 +    public void fillContext(Contexts.Builder context, Class<?> requestor) {
    7.74 +        context.register(Transfer.class, this, 50);
    7.75 +    }
    7.76 +
    7.77 +    @Override
    7.78 +    public void extract(Object obj, String[] props, Object[] values) {
    7.79 +        LoadJSON.extractJSON(obj, props, values);
    7.80 +    }
    7.81 +
    7.82 +    @Override
    7.83 +    public Object toJSON(InputStream is) throws IOException {
    7.84 +        return LoadJSON.parse(LoadJSON.readStream(is));
    7.85 +    }
    7.86 +
    7.87 +    @Override
    7.88 +    public void loadJSON(JSONCall call) {
    7.89 +        LoadJSON.loadJSON(call);
    7.90 +    }
    7.91 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/xhr4j/src/test/java/org/netbeans/html/xhr4j/JsonDynamicHTTP.java	Mon Feb 29 05:39:42 2016 +0100
     8.3 @@ -0,0 +1,262 @@
     8.4 +/**
     8.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     8.6 + *
     8.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
     8.8 + *
     8.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    8.10 + * Other names may be trademarks of their respective owners.
    8.11 + *
    8.12 + * The contents of this file are subject to the terms of either the GNU
    8.13 + * General Public License Version 2 only ("GPL") or the Common
    8.14 + * Development and Distribution License("CDDL") (collectively, the
    8.15 + * "License"). You may not use this file except in compliance with the
    8.16 + * License. You can obtain a copy of the License at
    8.17 + * http://www.netbeans.org/cddl-gplv2.html
    8.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    8.19 + * specific language governing permissions and limitations under the
    8.20 + * License.  When distributing the software, include this License Header
    8.21 + * Notice in each file and include the License file at
    8.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    8.23 + * particular file as subject to the "Classpath" exception as provided
    8.24 + * by Oracle in the GPL Version 2 section of the License file that
    8.25 + * accompanied this code. If applicable, add the following below the
    8.26 + * License Header, with the fields enclosed by brackets [] replaced by
    8.27 + * your own identifying information:
    8.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    8.29 + *
    8.30 + * Contributor(s):
    8.31 + *
    8.32 + * The Original Software is NetBeans. The Initial Developer of the Original
    8.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
    8.34 + *
    8.35 + * If you wish your version of this file to be governed by only the CDDL
    8.36 + * or only the GPL Version 2, indicate your decision by adding
    8.37 + * "[Contributor] elects to include this software in this distribution
    8.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    8.39 + * single choice of license, a recipient has the option to distribute
    8.40 + * your version of this file under either the CDDL, the GPL Version 2 or
    8.41 + * to extend the choice of license to its licensees as provided above.
    8.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    8.43 + * Version 2 license, then the option applies only if the new code is
    8.44 + * made subject to such option by the copyright holder.
    8.45 + */
    8.46 +package org.netbeans.html.xhr4j;
    8.47 +
    8.48 +import java.io.ByteArrayInputStream;
    8.49 +import java.io.ByteArrayOutputStream;
    8.50 +import java.io.IOException;
    8.51 +import java.io.InputStream;
    8.52 +import java.io.OutputStream;
    8.53 +import java.io.Reader;
    8.54 +import java.net.URI;
    8.55 +import java.net.URISyntaxException;
    8.56 +import java.util.ArrayList;
    8.57 +import java.util.List;
    8.58 +import java.util.logging.Level;
    8.59 +import java.util.logging.Logger;
    8.60 +import org.glassfish.grizzly.PortRange;
    8.61 +import org.glassfish.grizzly.http.server.HttpHandler;
    8.62 +import org.glassfish.grizzly.http.server.HttpServer;
    8.63 +import org.glassfish.grizzly.http.server.NetworkListener;
    8.64 +import org.glassfish.grizzly.http.server.Request;
    8.65 +import org.glassfish.grizzly.http.server.Response;
    8.66 +import org.glassfish.grizzly.http.server.ServerConfiguration;
    8.67 +import org.glassfish.grizzly.websockets.WebSocket;
    8.68 +import org.glassfish.grizzly.websockets.WebSocketAddOn;
    8.69 +import org.glassfish.grizzly.websockets.WebSocketApplication;
    8.70 +import org.glassfish.grizzly.websockets.WebSocketEngine;
    8.71 +
    8.72 +/**
    8.73 + *
    8.74 + * @author Jaroslav Tulach
    8.75 + */
    8.76 +final class JsonDynamicHTTP extends HttpHandler {
    8.77 +    private static int resourcesCount;
    8.78 +    private static List<Resource> resources;
    8.79 +    private static ServerConfiguration conf;
    8.80 +    private static HttpServer server;
    8.81 +
    8.82 +    private JsonDynamicHTTP() {
    8.83 +    }
    8.84 +
    8.85 +    static URI initServer() throws Exception {
    8.86 +        server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
    8.87 +        final WebSocketAddOn addon = new WebSocketAddOn();
    8.88 +        for (NetworkListener listener : server.getListeners()) {
    8.89 +            listener.registerAddOn(addon);
    8.90 +        }
    8.91 +        resources = new ArrayList<Resource>();
    8.92 +
    8.93 +        conf = server.getServerConfiguration();
    8.94 +        final JsonDynamicHTTP dh = new JsonDynamicHTTP();
    8.95 +
    8.96 +        conf.addHttpHandler(dh, "/");
    8.97 +
    8.98 +        server.start();
    8.99 +
   8.100 +        return pageURL("http", server, "/test.html");
   8.101 +    }
   8.102 +
   8.103 +    @Override
   8.104 +    public void service(Request request, Response response) throws Exception {
   8.105 +        if ("/test.html".equals(request.getRequestURI())) {
   8.106 +            response.setContentType("text/html");
   8.107 +            final InputStream is = JsonDynamicHTTP.class.getResourceAsStream("test.html");
   8.108 +            copyStream(is, response.getOutputStream(), null);
   8.109 +            return;
   8.110 +        }
   8.111 +        if ("/dynamic".equals(request.getRequestURI())) {
   8.112 +            String mimeType = request.getParameter("mimeType");
   8.113 +            List<String> params = new ArrayList<String>();
   8.114 +            boolean webSocket = false;
   8.115 +            for (int i = 0;; i++) {
   8.116 +                String p = request.getParameter("param" + i);
   8.117 +                if (p == null) {
   8.118 +                    break;
   8.119 +                }
   8.120 +                if ("protocol:ws".equals(p)) {
   8.121 +                    webSocket = true;
   8.122 +                    continue;
   8.123 +                }
   8.124 +                params.add(p);
   8.125 +            }
   8.126 +            final String cnt = request.getParameter("content");
   8.127 +            String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
   8.128 +            ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
   8.129 +            URI url;
   8.130 +            final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
   8.131 +            if (webSocket) {
   8.132 +                url = registerWebSocket(res);
   8.133 +            } else {
   8.134 +                url = registerResource(res);
   8.135 +            }
   8.136 +            response.getWriter().write(url.toString());
   8.137 +            response.getWriter().write("\n");
   8.138 +            return;
   8.139 +        }
   8.140 +
   8.141 +        for (Resource r : resources) {
   8.142 +            if (r.httpPath.equals(request.getRequestURI())) {
   8.143 +                response.setContentType(r.httpType);
   8.144 +                r.httpContent.reset();
   8.145 +                String[] params = null;
   8.146 +                if (r.parameters.length != 0) {
   8.147 +                    params = new String[r.parameters.length];
   8.148 +                    for (int i = 0; i < r.parameters.length; i++) {
   8.149 +                        params[i] = request.getParameter(r.parameters[i]);
   8.150 +                        if (params[i] == null) {
   8.151 +                            if ("http.method".equals(r.parameters[i])) {
   8.152 +                                params[i] = request.getMethod().toString();
   8.153 +                            } else if ("http.requestBody".equals(r.parameters[i])) {
   8.154 +                                Reader rdr = request.getReader();
   8.155 +                                StringBuilder sb = new StringBuilder();
   8.156 +                                for (;;) {
   8.157 +                                    int ch = rdr.read();
   8.158 +                                    if (ch == -1) {
   8.159 +                                        break;
   8.160 +                                    }
   8.161 +                                    sb.append((char) ch);
   8.162 +                                }
   8.163 +                                params[i] = sb.toString();
   8.164 +                            } else if (r.parameters[i].startsWith("http.header.")) {
   8.165 +                                params[i] = request.getHeader(r.parameters[i].substring(12));
   8.166 +                            }
   8.167 +                        }
   8.168 +                        if (params[i] == null) {
   8.169 +                            params[i] = "null";
   8.170 +                        }
   8.171 +                    }
   8.172 +                }
   8.173 +
   8.174 +                copyStream(r.httpContent, response.getOutputStream(), null, params);
   8.175 +            }
   8.176 +        }
   8.177 +    }
   8.178 +
   8.179 +    private URI registerWebSocket(Resource r) {
   8.180 +        WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
   8.181 +        return pageURL("ws", server, r.httpPath);
   8.182 +    }
   8.183 +
   8.184 +    private URI registerResource(Resource r) {
   8.185 +        if (!resources.contains(r)) {
   8.186 +            resources.add(r);
   8.187 +            conf.addHttpHandler(this, r.httpPath);
   8.188 +        }
   8.189 +        return pageURL("http", server, r.httpPath);
   8.190 +    }
   8.191 +
   8.192 +    private static URI pageURL(String proto, HttpServer server, final String page) {
   8.193 +        NetworkListener listener = server.getListeners().iterator().next();
   8.194 +        int port = listener.getPort();
   8.195 +        try {
   8.196 +            return new URI(proto + "://localhost:" + port + page);
   8.197 +        } catch (URISyntaxException ex) {
   8.198 +            throw new IllegalStateException(ex);
   8.199 +        }
   8.200 +    }
   8.201 +
   8.202 +    static final class Resource {
   8.203 +
   8.204 +        final InputStream httpContent;
   8.205 +        final String httpType;
   8.206 +        final String httpPath;
   8.207 +        final String[] parameters;
   8.208 +
   8.209 +        Resource(InputStream httpContent, String httpType, String httpPath,
   8.210 +            String[] parameters) {
   8.211 +            httpContent.mark(Integer.MAX_VALUE);
   8.212 +            this.httpContent = httpContent;
   8.213 +            this.httpType = httpType;
   8.214 +            this.httpPath = httpPath;
   8.215 +            this.parameters = parameters;
   8.216 +        }
   8.217 +    }
   8.218 +
   8.219 +    static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
   8.220 +        for (;;) {
   8.221 +            int ch = is.read();
   8.222 +            if (ch == -1) {
   8.223 +                break;
   8.224 +            }
   8.225 +            if (ch == '$' && params.length > 0) {
   8.226 +                int cnt = is.read() - '0';
   8.227 +                if (baseURL != null && cnt == 'U' - '0') {
   8.228 +                    os.write(baseURL.getBytes("UTF-8"));
   8.229 +                } else {
   8.230 +                    if (cnt >= 0 && cnt < params.length) {
   8.231 +                        os.write(params[cnt].getBytes("UTF-8"));
   8.232 +                    } else {
   8.233 +                        os.write('$');
   8.234 +                        os.write(cnt + '0');
   8.235 +                    }
   8.236 +                }
   8.237 +            } else {
   8.238 +                os.write(ch);
   8.239 +            }
   8.240 +        }
   8.241 +    }
   8.242 +
   8.243 +    private static class WS extends WebSocketApplication {
   8.244 +        private final Resource r;
   8.245 +
   8.246 +        private WS(Resource r) {
   8.247 +            this.r = r;
   8.248 +        }
   8.249 +
   8.250 +        @Override
   8.251 +        public void onMessage(WebSocket socket, String text) {
   8.252 +            try {
   8.253 +                r.httpContent.reset();
   8.254 +                ByteArrayOutputStream out = new ByteArrayOutputStream();
   8.255 +                copyStream(r.httpContent, out, null, text);
   8.256 +                String s = new String(out.toByteArray(), "UTF-8");
   8.257 +                socket.send(s);
   8.258 +            } catch (IOException ex) {
   8.259 +                LOG.log(Level.WARNING, null, ex);
   8.260 +            }
   8.261 +        }
   8.262 +        private static final Logger LOG = Logger.getLogger(WS.class.getName());
   8.263 +
   8.264 +    }
   8.265 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/xhr4j/src/test/java/org/netbeans/html/xhr4j/JsonFX.java	Mon Feb 29 05:39:42 2016 +0100
     9.3 @@ -0,0 +1,125 @@
     9.4 +/**
     9.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     9.6 + *
     9.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
     9.8 + *
     9.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    9.10 + * Other names may be trademarks of their respective owners.
    9.11 + *
    9.12 + * The contents of this file are subject to the terms of either the GNU
    9.13 + * General Public License Version 2 only ("GPL") or the Common
    9.14 + * Development and Distribution License("CDDL") (collectively, the
    9.15 + * "License"). You may not use this file except in compliance with the
    9.16 + * License. You can obtain a copy of the License at
    9.17 + * http://www.netbeans.org/cddl-gplv2.html
    9.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    9.19 + * specific language governing permissions and limitations under the
    9.20 + * License.  When distributing the software, include this License Header
    9.21 + * Notice in each file and include the License file at
    9.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    9.23 + * particular file as subject to the "Classpath" exception as provided
    9.24 + * by Oracle in the GPL Version 2 section of the License file that
    9.25 + * accompanied this code. If applicable, add the following below the
    9.26 + * License Header, with the fields enclosed by brackets [] replaced by
    9.27 + * your own identifying information:
    9.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    9.29 + *
    9.30 + * Contributor(s):
    9.31 + *
    9.32 + * The Original Software is NetBeans. The Initial Developer of the Original
    9.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
    9.34 + *
    9.35 + * If you wish your version of this file to be governed by only the CDDL
    9.36 + * or only the GPL Version 2, indicate your decision by adding
    9.37 + * "[Contributor] elects to include this software in this distribution
    9.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    9.39 + * single choice of license, a recipient has the option to distribute
    9.40 + * your version of this file under either the CDDL, the GPL Version 2 or
    9.41 + * to extend the choice of license to its licensees as provided above.
    9.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    9.43 + * Version 2 license, then the option applies only if the new code is
    9.44 + * made subject to such option by the copyright holder.
    9.45 + */
    9.46 +package org.netbeans.html.xhr4j;
    9.47 +
    9.48 +import java.lang.reflect.InvocationTargetException;
    9.49 +import java.lang.reflect.Method;
    9.50 +import javafx.application.Platform;
    9.51 +import org.netbeans.html.boot.impl.FnContext;
    9.52 +import org.netbeans.html.boot.spi.Fn;
    9.53 +import org.testng.ITest;
    9.54 +import org.testng.annotations.Test;
    9.55 +
    9.56 +/**
    9.57 + *
    9.58 + * @author Jaroslav Tulach
    9.59 + */
    9.60 +public final class JsonFX implements ITest, Runnable {
    9.61 +    private final Fn.Presenter p;
    9.62 +    private final Method m;
    9.63 +    private Object result;
    9.64 +    private Object inst;
    9.65 +    private int count;
    9.66 +
    9.67 +    JsonFX(Fn.Presenter p, Method m) {
    9.68 +        this.p = p;
    9.69 +        this.m = m;
    9.70 +    }
    9.71 +
    9.72 +    @Override
    9.73 +    public String getTestName() {
    9.74 +        return m.getName();
    9.75 +    }
    9.76 +
    9.77 +    @Test
    9.78 +    public synchronized void executeTest() throws Exception {
    9.79 +        if (result == null) {
    9.80 +            Platform.runLater(this);
    9.81 +            wait();
    9.82 +        }
    9.83 +        if (result instanceof Exception) {
    9.84 +            throw (Exception)result;
    9.85 +        }
    9.86 +        if (result instanceof Error) {
    9.87 +            throw (Error)result;
    9.88 +        }
    9.89 +    }
    9.90 +
    9.91 +    @Override
    9.92 +    public synchronized void run() {
    9.93 +        boolean notify = true;
    9.94 +        try {
    9.95 +            FnContext.currentPresenter(p);
    9.96 +            if (inst == null) {
    9.97 +                inst = m.getDeclaringClass().newInstance();
    9.98 +            }
    9.99 +            result = m.invoke(inst);
   9.100 +            if (result == null) {
   9.101 +                result = this;
   9.102 +            }
   9.103 +        } catch (InvocationTargetException ex) {
   9.104 +            Throwable r = ex.getTargetException();
   9.105 +            if (r instanceof InterruptedException) {
   9.106 +                if (count++ < 100) {
   9.107 +                    notify = false;
   9.108 +                    try {
   9.109 +                        Thread.sleep(100);
   9.110 +                    } catch (Exception ex1) {
   9.111 +                        // ignore and continue
   9.112 +                    }
   9.113 +                    Platform.runLater(this);
   9.114 +                    return;
   9.115 +                }
   9.116 +            }
   9.117 +            result = r;
   9.118 +        } catch (Exception ex) {
   9.119 +            result = ex;
   9.120 +        } finally {
   9.121 +            if (notify) {
   9.122 +                notifyAll();
   9.123 +            }
   9.124 +            FnContext.currentPresenter(null);
   9.125 +        }
   9.126 +    }
   9.127 +    
   9.128 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/xhr4j/src/test/java/org/netbeans/html/xhr4j/JsonKnockoutTest.java	Mon Feb 29 05:39:42 2016 +0100
    10.3 @@ -0,0 +1,217 @@
    10.4 +/**
    10.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    10.6 + *
    10.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
    10.8 + *
    10.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   10.10 + * Other names may be trademarks of their respective owners.
   10.11 + *
   10.12 + * The contents of this file are subject to the terms of either the GNU
   10.13 + * General Public License Version 2 only ("GPL") or the Common
   10.14 + * Development and Distribution License("CDDL") (collectively, the
   10.15 + * "License"). You may not use this file except in compliance with the
   10.16 + * License. You can obtain a copy of the License at
   10.17 + * http://www.netbeans.org/cddl-gplv2.html
   10.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   10.19 + * specific language governing permissions and limitations under the
   10.20 + * License.  When distributing the software, include this License Header
   10.21 + * Notice in each file and include the License file at
   10.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   10.23 + * particular file as subject to the "Classpath" exception as provided
   10.24 + * by Oracle in the GPL Version 2 section of the License file that
   10.25 + * accompanied this code. If applicable, add the following below the
   10.26 + * License Header, with the fields enclosed by brackets [] replaced by
   10.27 + * your own identifying information:
   10.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   10.29 + *
   10.30 + * Contributor(s):
   10.31 + *
   10.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   10.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
   10.34 + *
   10.35 + * If you wish your version of this file to be governed by only the CDDL
   10.36 + * or only the GPL Version 2, indicate your decision by adding
   10.37 + * "[Contributor] elects to include this software in this distribution
   10.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   10.39 + * single choice of license, a recipient has the option to distribute
   10.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   10.41 + * to extend the choice of license to its licensees as provided above.
   10.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   10.43 + * Version 2 license, then the option applies only if the new code is
   10.44 + * made subject to such option by the copyright holder.
   10.45 + */
   10.46 +package org.netbeans.html.xhr4j;
   10.47 +
   10.48 +import java.io.BufferedReader;
   10.49 +import java.io.IOException;
   10.50 +import java.io.InputStreamReader;
   10.51 +import java.lang.annotation.Annotation;
   10.52 +import java.lang.reflect.Method;
   10.53 +import java.net.URI;
   10.54 +import java.net.URISyntaxException;
   10.55 +import java.net.URL;
   10.56 +import java.net.URLConnection;
   10.57 +import java.util.ArrayList;
   10.58 +import java.util.List;
   10.59 +import java.util.Map;
   10.60 +import java.util.concurrent.Executor;
   10.61 +import java.util.concurrent.Executors;
   10.62 +import net.java.html.BrwsrCtx;
   10.63 +import net.java.html.boot.BrowserBuilder;
   10.64 +import net.java.html.js.JavaScriptBody;
   10.65 +import org.netbeans.html.boot.spi.Fn;
   10.66 +import org.netbeans.html.context.spi.Contexts;
   10.67 +import org.netbeans.html.json.spi.Technology;
   10.68 +import org.netbeans.html.json.tck.KOTest;
   10.69 +import org.netbeans.html.json.tck.KnockoutTCK;
   10.70 +import org.netbeans.html.ko4j.KO4J;
   10.71 +import org.openide.util.lookup.ServiceProvider;
   10.72 +import org.testng.Assert;
   10.73 +import static org.testng.Assert.*;
   10.74 +import org.testng.annotations.Factory;
   10.75 +
   10.76 +/**
   10.77 + *
   10.78 + * @author Jaroslav Tulach
   10.79 + */
   10.80 +@ServiceProvider(service = KnockoutTCK.class)
   10.81 +public final class JsonKnockoutTest extends KnockoutTCK {
   10.82 +    private static Class<?> browserClass;
   10.83 +    private static Fn.Presenter browserContext;
   10.84 +    
   10.85 +    public JsonKnockoutTest() {
   10.86 +    }
   10.87 +    
   10.88 +    @Factory public static Object[] compatibilityTests() throws Exception {
   10.89 +        Class[] arr = testClasses();
   10.90 +        for (int i = 0; i < arr.length; i++) {
   10.91 +            assertEquals(arr[i].getClassLoader(),
   10.92 +                JsonKnockoutTest.class.getClassLoader(),
   10.93 +                "All classes loaded by the same classloader"
   10.94 +            );
   10.95 +        }
   10.96 +        
   10.97 +        URI uri = JsonDynamicHTTP.initServer();
   10.98 +    
   10.99 +        final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(JsonKnockoutTest.class).
  10.100 +            loadPage(uri.toString()).
  10.101 +            invoke("initialized");
  10.102 +        
  10.103 +        Executors.newSingleThreadExecutor().submit(new Runnable() {
  10.104 +            @Override
  10.105 +            public void run() {
  10.106 +                bb.showAndWait();
  10.107 +            }
  10.108 +        });
  10.109 +        
  10.110 +        ClassLoader l = getClassLoader();
  10.111 +        List<Object> res = new ArrayList<Object>();
  10.112 +        for (int i = 0; i < arr.length; i++) {
  10.113 +            Class<?> c = Class.forName(arr[i].getName(), true, l);
  10.114 +            Class<? extends Annotation> koTest = 
  10.115 +                c.getClassLoader().loadClass(KOTest.class.getName()).
  10.116 +                asSubclass(Annotation.class);
  10.117 +            for (Method m : c.getMethods()) {
  10.118 +                if (m.getAnnotation(koTest) != null) {
  10.119 +                    res.add(new JsonFX(browserContext, m));
  10.120 +                }
  10.121 +            }
  10.122 +        }
  10.123 +        return res.toArray();
  10.124 +    }
  10.125 +
  10.126 +    static synchronized ClassLoader getClassLoader() throws InterruptedException {
  10.127 +        while (browserClass == null) {
  10.128 +            JsonKnockoutTest.class.wait();
  10.129 +        }
  10.130 +        return browserClass.getClassLoader();
  10.131 +    }
  10.132 +    
  10.133 +    public static synchronized void initialized(Class<?> browserCls) throws Exception {
  10.134 +        browserClass = browserCls;
  10.135 +        browserContext = Fn.activePresenter();
  10.136 +        JsonKnockoutTest.class.notifyAll();
  10.137 +    }
  10.138 +    
  10.139 +    public static void initialized() throws Exception {
  10.140 +        Assert.assertSame(JsonKnockoutTest.class.getClassLoader(),
  10.141 +            ClassLoader.getSystemClassLoader(),
  10.142 +            "No special classloaders"
  10.143 +        );
  10.144 +        JsonKnockoutTest.initialized(JsonKnockoutTest.class);
  10.145 +    }
  10.146 +
  10.147 +    @Override
  10.148 +    public boolean canFailWebSocketTest() {
  10.149 +        return true;
  10.150 +    }
  10.151 +    
  10.152 +    @Override
  10.153 +    public BrwsrCtx createContext() {
  10.154 +        KO4J ko = new KO4J(browserContext);
  10.155 +        XmlHttpResourceContext tc = new XmlHttpResourceContext();
  10.156 +        Contexts.Builder cb = Contexts.newBuilder().
  10.157 +            register(Technology.class, ko.knockout(), 10).
  10.158 +            register(Executor.class, (Executor)browserContext, 10).
  10.159 +            register(Fn.Presenter.class, (Fn.Presenter)browserContext, 10);
  10.160 +        tc.fillContext(cb, browserClass);
  10.161 +        return cb.build();
  10.162 +    }
  10.163 +
  10.164 +    @Override
  10.165 +    public Object createJSON(Map<String, Object> values) {
  10.166 +        Object json = createJSON();
  10.167 +        for (Map.Entry<String, Object> entry : values.entrySet()) {
  10.168 +            setProperty(json, entry.getKey(), entry.getValue());
  10.169 +        }
  10.170 +        return json;
  10.171 +    }
  10.172 +
  10.173 +    @JavaScriptBody(args = {}, body = "return new Object();")
  10.174 +    private static native Object createJSON();
  10.175 +
  10.176 +    @JavaScriptBody(args = {"json", "key", "value"}, body = "json[key] = value;")
  10.177 +    private static native void setProperty(Object json, String key, Object value);
  10.178 +
  10.179 +    @Override
  10.180 +    @JavaScriptBody(args = { "s", "args" }, body = ""
  10.181 +        + "var f = new Function(s); "
  10.182 +        + "return f.apply(null, args);"
  10.183 +    )
  10.184 +    public native Object executeScript(String script, Object[] arguments);
  10.185 +
  10.186 +    @JavaScriptBody(args = {  }, body = 
  10.187 +          "var h;"
  10.188 +        + "if (!!window && !!window.location && !!window.location.href)\n"
  10.189 +        + "  h = window.location.href;\n"
  10.190 +        + "else "
  10.191 +        + "  h = null;"
  10.192 +        + "return h;\n"
  10.193 +    )
  10.194 +    private static native String findBaseURL();
  10.195 +    
  10.196 +    @Override
  10.197 +    public URI prepareURL(String content, String mimeType, String[] parameters) {
  10.198 +        try {
  10.199 +            final URL baseURL = new URL(findBaseURL());
  10.200 +            StringBuilder sb = new StringBuilder();
  10.201 +            sb.append("/dynamic?mimeType=").append(mimeType);
  10.202 +            for (int i = 0; i < parameters.length; i++) {
  10.203 +                sb.append("&param" + i).append("=").append(parameters[i]);
  10.204 +            }
  10.205 +            String mangle = content.replace("\n", "%0a")
  10.206 +                .replace("\"", "\\\"").replace(" ", "%20");
  10.207 +            sb.append("&content=").append(mangle);
  10.208 +
  10.209 +            URL query = new URL(baseURL, sb.toString());
  10.210 +            URLConnection c = query.openConnection();
  10.211 +            BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
  10.212 +            URI connectTo = new URI(br.readLine());
  10.213 +            return connectTo;
  10.214 +        } catch (IOException ex) {
  10.215 +            throw new IllegalStateException(ex);
  10.216 +        } catch (URISyntaxException ex) {
  10.217 +            throw new IllegalStateException(ex);
  10.218 +        }
  10.219 +    }
  10.220 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/xhr4j/src/test/resources/org/netbeans/html/xhr4j/test.html	Mon Feb 29 05:39:42 2016 +0100
    11.3 @@ -0,0 +1,56 @@
    11.4 +<!--
    11.5 +
    11.6 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    11.7 +
    11.8 +    Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
    11.9 +
   11.10 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   11.11 +    Other names may be trademarks of their respective owners.
   11.12 +
   11.13 +    The contents of this file are subject to the terms of either the GNU
   11.14 +    General Public License Version 2 only ("GPL") or the Common
   11.15 +    Development and Distribution License("CDDL") (collectively, the
   11.16 +    "License"). You may not use this file except in compliance with the
   11.17 +    License. You can obtain a copy of the License at
   11.18 +    http://www.netbeans.org/cddl-gplv2.html
   11.19 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   11.20 +    specific language governing permissions and limitations under the
   11.21 +    License.  When distributing the software, include this License Header
   11.22 +    Notice in each file and include the License file at
   11.23 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   11.24 +    particular file as subject to the "Classpath" exception as provided
   11.25 +    by Oracle in the GPL Version 2 section of the License file that
   11.26 +    accompanied this code. If applicable, add the following below the
   11.27 +    License Header, with the fields enclosed by brackets [] replaced by
   11.28 +    your own identifying information:
   11.29 +    "Portions Copyrighted [year] [name of copyright owner]"
   11.30 +
   11.31 +    Contributor(s):
   11.32 +
   11.33 +    The Original Software is NetBeans. The Initial Developer of the Original
   11.34 +    Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
   11.35 +
   11.36 +    If you wish your version of this file to be governed by only the CDDL
   11.37 +    or only the GPL Version 2, indicate your decision by adding
   11.38 +    "[Contributor] elects to include this software in this distribution
   11.39 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
   11.40 +    single choice of license, a recipient has the option to distribute
   11.41 +    your version of this file under either the CDDL, the GPL Version 2 or
   11.42 +    to extend the choice of license to its licensees as provided above.
   11.43 +    However, if you add GPL Version 2 code and therefore, elected the GPL
   11.44 +    Version 2 license, then the option applies only if the new code is
   11.45 +    made subject to such option by the copyright holder.
   11.46 +
   11.47 +-->
   11.48 +<!DOCTYPE html>
   11.49 +<html>
   11.50 +    <head>
   11.51 +        <title>XHR via Java Harness</title>
   11.52 +        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   11.53 +        <meta name="viewport" content="width=device-width">
   11.54 +    </head>
   11.55 +    <body>
   11.56 +        <h1>XHR via Java Harness</h1>
   11.57 +    </body>
   11.58 +    <script></script>
   11.59 +</html>