1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/boot-agent-test/pom.xml Tue Dec 09 08:33:22 2014 +0100
1.3 @@ -0,0 +1,61 @@
1.4 +<?xml version="1.0" encoding="UTF-8"?>
1.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">
1.6 + <modelVersion>4.0.0</modelVersion>
1.7 + <parent>
1.8 + <groupId>org.netbeans.html</groupId>
1.9 + <artifactId>pom</artifactId>
1.10 + <version>2.0-SNAPSHOT</version>
1.11 + </parent>
1.12 + <artifactId>boot-agent-test</artifactId>
1.13 + <packaging>jar</packaging>
1.14 + <name>Dynamic Boot Test</name>
1.15 + <build>
1.16 + <plugins>
1.17 + <plugin>
1.18 + <groupId>org.apache.maven.plugins</groupId>
1.19 + <artifactId>maven-deploy-plugin</artifactId>
1.20 + <configuration>
1.21 + <skip>true</skip>
1.22 + </configuration>
1.23 + </plugin>
1.24 + </plugins>
1.25 + </build>
1.26 + <dependencies>
1.27 + <dependency>
1.28 + <groupId>org.testng</groupId>
1.29 + <artifactId>testng</artifactId>
1.30 + <scope>test</scope>
1.31 + </dependency>
1.32 + <dependency>
1.33 + <groupId>org.netbeans.html</groupId>
1.34 + <artifactId>net.java.html</artifactId>
1.35 + <version>${project.version}</version>
1.36 + <scope>test</scope>
1.37 + <type>jar</type>
1.38 + </dependency>
1.39 + <dependency>
1.40 + <groupId>org.netbeans.html</groupId>
1.41 + <artifactId>net.java.html.boot</artifactId>
1.42 + <version>${project.version}</version>
1.43 + <scope>test</scope>
1.44 + <type>jar</type>
1.45 + </dependency>
1.46 + <dependency>
1.47 + <groupId>org.netbeans.api</groupId>
1.48 + <artifactId>org-openide-util-lookup</artifactId>
1.49 + <scope>test</scope>
1.50 + <type>jar</type>
1.51 + </dependency>
1.52 + <dependency>
1.53 + <groupId>${project.groupId}</groupId>
1.54 + <artifactId>net.java.html.boot.fx</artifactId>
1.55 + <version>${project.version}</version>
1.56 + <scope>test</scope>
1.57 + </dependency>
1.58 + <dependency>
1.59 + <groupId>org.ow2.asm</groupId>
1.60 + <artifactId>asm</artifactId>
1.61 + <scope>test</scope>
1.62 + </dependency>
1.63 + </dependencies>
1.64 +</project>
1.65 \ No newline at end of file
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/boot-agent-test/src/test/java/org/netbeans/html/bootagent/DynamicClassLoaderTest.java Tue Dec 09 08:33:22 2014 +0100
2.3 @@ -0,0 +1,126 @@
2.4 +/**
2.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
2.6 + *
2.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
2.8 + *
2.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
2.10 + * Other names may be trademarks of their respective owners.
2.11 + *
2.12 + * The contents of this file are subject to the terms of either the GNU
2.13 + * General Public License Version 2 only ("GPL") or the Common
2.14 + * Development and Distribution License("CDDL") (collectively, the
2.15 + * "License"). You may not use this file except in compliance with the
2.16 + * License. You can obtain a copy of the License at
2.17 + * http://www.netbeans.org/cddl-gplv2.html
2.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
2.19 + * specific language governing permissions and limitations under the
2.20 + * License. When distributing the software, include this License Header
2.21 + * Notice in each file and include the License file at
2.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
2.23 + * particular file as subject to the "Classpath" exception as provided
2.24 + * by Oracle in the GPL Version 2 section of the License file that
2.25 + * accompanied this code. If applicable, add the following below the
2.26 + * License Header, with the fields enclosed by brackets [] replaced by
2.27 + * your own identifying information:
2.28 + * "Portions Copyrighted [year] [name of copyright owner]"
2.29 + *
2.30 + * Contributor(s):
2.31 + *
2.32 + * The Original Software is NetBeans. The Initial Developer of the Original
2.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
2.34 + *
2.35 + * If you wish your version of this file to be governed by only the CDDL
2.36 + * or only the GPL Version 2, indicate your decision by adding
2.37 + * "[Contributor] elects to include this software in this distribution
2.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
2.39 + * single choice of license, a recipient has the option to distribute
2.40 + * your version of this file under either the CDDL, the GPL Version 2 or
2.41 + * to extend the choice of license to its licensees as provided above.
2.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
2.43 + * Version 2 license, then the option applies only if the new code is
2.44 + * made subject to such option by the copyright holder.
2.45 + */
2.46 +package org.netbeans.html.bootagent;
2.47 +
2.48 +import java.lang.reflect.Field;
2.49 +import java.lang.reflect.Method;
2.50 +import java.lang.reflect.Modifier;
2.51 +import java.util.ArrayList;
2.52 +import java.util.List;
2.53 +import java.util.concurrent.Executors;
2.54 +import net.java.html.BrwsrCtx;
2.55 +import net.java.html.boot.BrowserBuilder;
2.56 +import org.netbeans.html.boot.spi.Fn;
2.57 +import org.testng.Assert;
2.58 +import static org.testng.Assert.assertNotSame;
2.59 +import static org.testng.Assert.assertSame;
2.60 +import org.testng.annotations.Factory;
2.61 +
2.62 +/**
2.63 + *
2.64 + * @author Jaroslav Tulach
2.65 + */
2.66 +public class DynamicClassLoaderTest {
2.67 + private static Class<?> browserClass;
2.68 + private static Fn.Presenter browserPresenter;
2.69 +
2.70 + public DynamicClassLoaderTest() {
2.71 + }
2.72 +
2.73 + @Factory public static Object[] compatibilityTests() throws Exception {
2.74 + final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(DynamicClassLoaderTest.class).
2.75 + loadPage("empty.html").
2.76 + invoke("initialized");
2.77 +
2.78 + Executors.newSingleThreadExecutor().submit(new Runnable() {
2.79 + @Override
2.80 + public void run() {
2.81 + bb.showAndWait();
2.82 + }
2.83 + });
2.84 +
2.85 + List<Object> res = new ArrayList<Object>();
2.86 +
2.87 + Class[] arr = new Class[] { loadClass() };
2.88 + for (Class c : arr) {
2.89 + for (Method m : c.getDeclaredMethods()) {
2.90 + if ((m.getModifiers() & Modifier.PUBLIC) != 0) {
2.91 + res.add(new KOFx(browserPresenter, m));
2.92 + }
2.93 + }
2.94 + }
2.95 + return res.toArray();
2.96 + }
2.97 +
2.98 + static synchronized Class<?> loadClass() throws InterruptedException {
2.99 + while (browserClass == null) {
2.100 + DynamicClassLoaderTest.class.wait();
2.101 + }
2.102 + return browserClass;
2.103 + }
2.104 +
2.105 + public static void ready(Class<?> browserCls) throws Exception {
2.106 + Class<?> origClazz = ClassLoader.getSystemClassLoader().loadClass(DynamicClassLoaderTest.class.getName());
2.107 + final Field f1 = origClazz.getDeclaredField("browserClass");
2.108 + f1.setAccessible(true);
2.109 + f1.set(null, browserCls);
2.110 + final Field f2 = origClazz.getDeclaredField("browserPresenter");
2.111 + f2.setAccessible(true);
2.112 + f2.set(null, Fn.activePresenter());
2.113 + synchronized (origClazz) {
2.114 + origClazz.notifyAll();
2.115 + }
2.116 + }
2.117 +
2.118 + public static void initialized() throws Exception {
2.119 + BrwsrCtx b1 = BrwsrCtx.findDefault(DynamicClassLoaderTest.class);
2.120 + assertNotSame(b1, BrwsrCtx.EMPTY, "Browser context is not empty");
2.121 + BrwsrCtx b2 = BrwsrCtx.findDefault(DynamicClassLoaderTest.class);
2.122 + assertSame(b1, b2, "Browser context remains stable");
2.123 + Assert.assertNotSame(DynamicClassLoaderTest.class.getClassLoader(),
2.124 + ClassLoader.getSystemClassLoader(),
2.125 + "Should use special classloader, not system one"
2.126 + );
2.127 + DynamicClassLoaderTest.ready(JavaScriptBodyTst.class);
2.128 + }
2.129 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/boot-agent-test/src/test/java/org/netbeans/html/bootagent/JavaScriptBodyTst.java Tue Dec 09 08:33:22 2014 +0100
3.3 @@ -0,0 +1,63 @@
3.4 +/**
3.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3.6 + *
3.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
3.8 + *
3.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
3.10 + * Other names may be trademarks of their respective owners.
3.11 + *
3.12 + * The contents of this file are subject to the terms of either the GNU
3.13 + * General Public License Version 2 only ("GPL") or the Common
3.14 + * Development and Distribution License("CDDL") (collectively, the
3.15 + * "License"). You may not use this file except in compliance with the
3.16 + * License. You can obtain a copy of the License at
3.17 + * http://www.netbeans.org/cddl-gplv2.html
3.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
3.19 + * specific language governing permissions and limitations under the
3.20 + * License. When distributing the software, include this License Header
3.21 + * Notice in each file and include the License file at
3.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
3.23 + * particular file as subject to the "Classpath" exception as provided
3.24 + * by Oracle in the GPL Version 2 section of the License file that
3.25 + * accompanied this code. If applicable, add the following below the
3.26 + * License Header, with the fields enclosed by brackets [] replaced by
3.27 + * your own identifying information:
3.28 + * "Portions Copyrighted [year] [name of copyright owner]"
3.29 + *
3.30 + * Contributor(s):
3.31 + *
3.32 + * The Original Software is NetBeans. The Initial Developer of the Original
3.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
3.34 + *
3.35 + * If you wish your version of this file to be governed by only the CDDL
3.36 + * or only the GPL Version 2, indicate your decision by adding
3.37 + * "[Contributor] elects to include this software in this distribution
3.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
3.39 + * single choice of license, a recipient has the option to distribute
3.40 + * your version of this file under either the CDDL, the GPL Version 2 or
3.41 + * to extend the choice of license to its licensees as provided above.
3.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
3.43 + * Version 2 license, then the option applies only if the new code is
3.44 + * made subject to such option by the copyright holder.
3.45 + */
3.46 +package org.netbeans.html.bootagent;
3.47 +
3.48 +import net.java.html.js.JavaScriptBody;
3.49 +
3.50 +/**
3.51 + *
3.52 + * @author Jaroslav Tulach
3.53 + */
3.54 +public class JavaScriptBodyTst {
3.55 +
3.56 + public JavaScriptBodyTst() {
3.57 + }
3.58 +
3.59 + public void assert42() {
3.60 + int v = mul(7, 6);
3.61 + assert v == 42 : "Really 42: " + v;
3.62 + }
3.63 +
3.64 + @JavaScriptBody(args = { "x", "y" }, body = "return x * y;")
3.65 + private static native int mul(int x, int y);
3.66 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/boot-agent-test/src/test/java/org/netbeans/html/bootagent/KOFx.java Tue Dec 09 08:33:22 2014 +0100
4.3 @@ -0,0 +1,125 @@
4.4 +/**
4.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4.6 + *
4.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
4.8 + *
4.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
4.10 + * Other names may be trademarks of their respective owners.
4.11 + *
4.12 + * The contents of this file are subject to the terms of either the GNU
4.13 + * General Public License Version 2 only ("GPL") or the Common
4.14 + * Development and Distribution License("CDDL") (collectively, the
4.15 + * "License"). You may not use this file except in compliance with the
4.16 + * License. You can obtain a copy of the License at
4.17 + * http://www.netbeans.org/cddl-gplv2.html
4.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
4.19 + * specific language governing permissions and limitations under the
4.20 + * License. When distributing the software, include this License Header
4.21 + * Notice in each file and include the License file at
4.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
4.23 + * particular file as subject to the "Classpath" exception as provided
4.24 + * by Oracle in the GPL Version 2 section of the License file that
4.25 + * accompanied this code. If applicable, add the following below the
4.26 + * License Header, with the fields enclosed by brackets [] replaced by
4.27 + * your own identifying information:
4.28 + * "Portions Copyrighted [year] [name of copyright owner]"
4.29 + *
4.30 + * Contributor(s):
4.31 + *
4.32 + * The Original Software is NetBeans. The Initial Developer of the Original
4.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
4.34 + *
4.35 + * If you wish your version of this file to be governed by only the CDDL
4.36 + * or only the GPL Version 2, indicate your decision by adding
4.37 + * "[Contributor] elects to include this software in this distribution
4.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
4.39 + * single choice of license, a recipient has the option to distribute
4.40 + * your version of this file under either the CDDL, the GPL Version 2 or
4.41 + * to extend the choice of license to its licensees as provided above.
4.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
4.43 + * Version 2 license, then the option applies only if the new code is
4.44 + * made subject to such option by the copyright holder.
4.45 + */
4.46 +package org.netbeans.html.bootagent;
4.47 +
4.48 +import java.lang.reflect.InvocationTargetException;
4.49 +import java.lang.reflect.Method;
4.50 +import javafx.application.Platform;
4.51 +import org.netbeans.html.boot.impl.FnContext;
4.52 +import org.netbeans.html.boot.spi.Fn;
4.53 +import org.testng.IHookCallBack;
4.54 +import org.testng.IHookable;
4.55 +import org.testng.ITest;
4.56 +import org.testng.ITestResult;
4.57 +import org.testng.annotations.Test;
4.58 +
4.59 +/**
4.60 + *
4.61 + * @author Jaroslav Tulach
4.62 + */
4.63 +public final class KOFx implements ITest, IHookable, Runnable {
4.64 + private final Fn.Presenter p;
4.65 + private final Method m;
4.66 + private Object result;
4.67 + private Object inst;
4.68 +
4.69 + KOFx(Fn.Presenter p, Method m) {
4.70 + this.p = p;
4.71 + this.m = m;
4.72 + }
4.73 +
4.74 + @Override
4.75 + public String getTestName() {
4.76 + return m.getName();
4.77 + }
4.78 +
4.79 + @Test
4.80 + public synchronized void executeTest() throws Exception {
4.81 + if (result == null) {
4.82 + Platform.runLater(this);
4.83 + wait();
4.84 + }
4.85 + if (result instanceof Exception) {
4.86 + throw (Exception)result;
4.87 + }
4.88 + if (result instanceof Error) {
4.89 + throw (Error)result;
4.90 + }
4.91 + }
4.92 +
4.93 + @Override
4.94 + public synchronized void run() {
4.95 + boolean notify = true;
4.96 + try {
4.97 + FnContext.currentPresenter(p);
4.98 + if (inst == null) {
4.99 + inst = m.getDeclaringClass().newInstance();
4.100 + }
4.101 + result = m.invoke(inst);
4.102 + if (result == null) {
4.103 + result = this;
4.104 + }
4.105 + } catch (InvocationTargetException ex) {
4.106 + Throwable r = ex.getTargetException();
4.107 + if (r instanceof InterruptedException) {
4.108 + notify = false;
4.109 + Platform.runLater(this);
4.110 + return;
4.111 + }
4.112 + result = r;
4.113 + } catch (Exception ex) {
4.114 + result = ex;
4.115 + } finally {
4.116 + if (notify) {
4.117 + notifyAll();
4.118 + }
4.119 + FnContext.currentPresenter(null);
4.120 + }
4.121 + }
4.122 +
4.123 + @Override
4.124 + public void run(IHookCallBack ihcb, ITestResult itr) {
4.125 + ihcb.runTestMethod(itr);
4.126 + }
4.127 +
4.128 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/boot-agent-test/src/test/resources/org/netbeans/html/bootagent/empty.html Tue Dec 09 08:33:22 2014 +0100
5.3 @@ -0,0 +1,55 @@
5.4 +<!--
5.5 +
5.6 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
5.7 +
5.8 + Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
5.9 +
5.10 + Oracle and Java are registered trademarks of Oracle and/or its affiliates.
5.11 + Other names may be trademarks of their respective owners.
5.12 +
5.13 + The contents of this file are subject to the terms of either the GNU
5.14 + General Public License Version 2 only ("GPL") or the Common
5.15 + Development and Distribution License("CDDL") (collectively, the
5.16 + "License"). You may not use this file except in compliance with the
5.17 + License. You can obtain a copy of the License at
5.18 + http://www.netbeans.org/cddl-gplv2.html
5.19 + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
5.20 + specific language governing permissions and limitations under the
5.21 + License. When distributing the software, include this License Header
5.22 + Notice in each file and include the License file at
5.23 + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
5.24 + particular file as subject to the "Classpath" exception as provided
5.25 + by Oracle in the GPL Version 2 section of the License file that
5.26 + accompanied this code. If applicable, add the following below the
5.27 + License Header, with the fields enclosed by brackets [] replaced by
5.28 + your own identifying information:
5.29 + "Portions Copyrighted [year] [name of copyright owner]"
5.30 +
5.31 + Contributor(s):
5.32 +
5.33 + The Original Software is NetBeans. The Initial Developer of the Original
5.34 + Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
5.35 +
5.36 + If you wish your version of this file to be governed by only the CDDL
5.37 + or only the GPL Version 2, indicate your decision by adding
5.38 + "[Contributor] elects to include this software in this distribution
5.39 + under the [CDDL or GPL Version 2] license." If you do not indicate a
5.40 + single choice of license, a recipient has the option to distribute
5.41 + your version of this file under either the CDDL, the GPL Version 2 or
5.42 + to extend the choice of license to its licensees as provided above.
5.43 + However, if you add GPL Version 2 code and therefore, elected the GPL
5.44 + Version 2 license, then the option applies only if the new code is
5.45 + made subject to such option by the copyright holder.
5.46 +
5.47 +-->
5.48 +<!DOCTYPE html>
5.49 +<html>
5.50 + <head>
5.51 + <title>Bootstrap Dynamically</title>
5.52 + <meta charset="UTF-8">
5.53 + <meta name="viewport" content="width=device-width, initial-scale=1.0">
5.54 + </head>
5.55 + <body>
5.56 + <div>Bootstrap Dynamically</div>
5.57 + </body>
5.58 +</html>
6.1 --- a/boot-fx/src/main/java/net/java/html/boot/fx/FXBrowsers.java Tue Dec 09 07:23:22 2014 +0100
6.2 +++ b/boot-fx/src/main/java/net/java/html/boot/fx/FXBrowsers.java Tue Dec 09 08:33:22 2014 +0100
6.3 @@ -52,6 +52,8 @@
6.4 import net.java.html.boot.BrowserBuilder;
6.5 import net.java.html.js.JavaScriptBody;
6.6 import org.netbeans.html.boot.fx.AbstractFXPresenter;
6.7 +import org.netbeans.html.context.spi.Contexts;
6.8 +import org.netbeans.html.context.spi.Contexts.Id;
6.9
6.10 /** Utility methods to use {@link WebView} and {@link JavaScriptBody} code
6.11 * in existing <em>JavaFX</em> applications.
6.12 @@ -82,6 +84,16 @@
6.13 * <p>
6.14 * This method sets {@link WebView#getUserData()} and {@link #runInBrowser(javafx.scene.web.WebView, java.lang.Runnable)}
6.15 * relies on the value. Please don't alter it.
6.16 + * <p>
6.17 + * Since introduction of {@link Id technology identifiers} the
6.18 + * provided <code>args</code> strings are also passed to the
6.19 + * {@link BrwsrCtx context} when it is being
6.20 + * {@link Contexts#newBuilder(java.lang.Object...) created}
6.21 + * and can influence the selection
6.22 + * of available technologies
6.23 + * (like {@link org.netbeans.html.json.spi.Technology},
6.24 + * {@link org.netbeans.html.json.spi.Transfer} or
6.25 + * {@link org.netbeans.html.json.spi.WSTransfer}).
6.26 *
6.27 * @param webView the instance of Web View to tweak
6.28 * @param url the URL of the HTML page to load into the view
6.29 @@ -94,7 +106,10 @@
6.30 Class<?> onPageLoad, String methodName,
6.31 String... args
6.32 ) {
6.33 - BrowserBuilder.newBrowser(new Load(webView)).
6.34 + Object[] context = new Object[args.length + 1];
6.35 + System.arraycopy(args, 0, context, 1, args.length);
6.36 + context[0] = new Load(webView);
6.37 + BrowserBuilder.newBrowser(context).
6.38 loadPage(url.toExternalForm()).
6.39 loadClass(onPageLoad).
6.40 invoke(methodName, args).
6.41 @@ -126,8 +141,8 @@
6.42
6.43 /** Enables the Java/JavaScript bridge (that supports {@link JavaScriptBody} and co.)
6.44 * in the provided <code>webView</code>. This method returns
6.45 - * immediately. Once the support is active, it calls back specified
6.46 - * method in <code>onPageLoad</code>'s run method.
6.47 + * immediately. Once the support is active, it calls back {@link Runnable#run() run}
6.48 + * method in <code>onPageLoad</code>.
6.49 * This is more convenient way to initialize the webview,
6.50 * but it requires one to make sure
6.51 * all {@link JavaScriptBody} methods has been post-processed during
6.52 @@ -145,7 +160,37 @@
6.53 public static void load(
6.54 WebView webView, final URL url, Runnable onPageLoad, ClassLoader loader
6.55 ) {
6.56 - BrowserBuilder.newBrowser(new Load(webView)).
6.57 + load(webView, url, onPageLoad, loader, new Object[0]);
6.58 + }
6.59 +
6.60 + /** Enables the Java/JavaScript bridge (that supports {@link JavaScriptBody} and co.)
6.61 + * in the provided <code>webView</code>. This method returns
6.62 + * immediately. Once the support is active, it calls back {@link Runnable#run() run}
6.63 + * method in <code>onPageLoad</code>.
6.64 + * This is more convenient way to initialize the webview,
6.65 + * but it requires one to make sure
6.66 + * all {@link JavaScriptBody} methods has been post-processed during
6.67 + * compilation and there will be no need to instantiate new classloader.
6.68 + * <p>
6.69 + * This method sets {@link WebView#getUserData()} and {@link #runInBrowser(javafx.scene.web.WebView, java.lang.Runnable)}
6.70 + * relies on the value. Please don't alter it.
6.71 + *
6.72 + * @param webView the instance of Web View to tweak
6.73 + * @param url the URL of the HTML page to load into the view
6.74 + * @param onPageLoad callback to call when the page is ready
6.75 + * @param loader the loader to use when constructing initial {@link BrwsrCtx} or <code>null</code>
6.76 + * @param context additonal configuration to pass to {@link BrowserBuilder#newBrowser(java.lang.Object...)}
6.77 + * and {@link Contexts#newBuilder(java.lang.Object...)} factory methods
6.78 + * @since 1.1
6.79 + */
6.80 + public static void load(
6.81 + WebView webView, final URL url, Runnable onPageLoad, ClassLoader loader,
6.82 + Object... context
6.83 + ) {
6.84 + Object[] newCtx = new Object[context.length + 1];
6.85 + System.arraycopy(context, 0, newCtx, 1, context.length);
6.86 + newCtx[0] = new Load(webView);
6.87 + BrowserBuilder.newBrowser(newCtx).
6.88 loadPage(url.toExternalForm()).
6.89 loadFinished(onPageLoad).
6.90 classloader(loader).
7.1 --- a/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXToolbar.java Tue Dec 09 07:23:22 2014 +0100
7.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXToolbar.java Tue Dec 09 08:33:22 2014 +0100
7.3 @@ -42,8 +42,6 @@
7.4 */
7.5 package org.netbeans.html.boot.fx;
7.6
7.7 -import java.io.IOException;
7.8 -import java.net.URISyntaxException;
7.9 import java.util.ArrayList;
7.10 import java.util.List;
7.11 import java.util.logging.Level;
7.12 @@ -55,10 +53,11 @@
7.13 import javafx.collections.FXCollections;
7.14 import javafx.event.ActionEvent;
7.15 import javafx.event.EventHandler;
7.16 +import javafx.scene.Group;
7.17 +import javafx.scene.Scene;
7.18 import javafx.scene.control.Button;
7.19 import javafx.scene.control.CheckBox;
7.20 import javafx.scene.control.ComboBox;
7.21 -import javafx.scene.control.ScrollPane;
7.22 import javafx.scene.control.Separator;
7.23 import javafx.scene.control.Toggle;
7.24 import javafx.scene.control.ToggleButton;
7.25 @@ -69,6 +68,9 @@
7.26 import javafx.scene.image.ImageView;
7.27 import javafx.scene.layout.BorderPane;
7.28 import javafx.scene.web.WebView;
7.29 +import javafx.stage.Screen;
7.30 +import javafx.stage.Stage;
7.31 +import javafx.stage.Window;
7.32
7.33 final class FXToolbar extends ToolBar {
7.34 private final ArrayList<ResizeBtn> resizeButtons;
7.35 @@ -185,21 +187,25 @@
7.36
7.37 }
7.38
7.39 - private void _resize( final double width, final double height ) {
7.40 - ScrollPane scroll;
7.41 - if (container.getCenter() == webView) {
7.42 - scroll = new ScrollPane();
7.43 - scroll.setContent(webView);
7.44 - container.setCenter(scroll);
7.45 - } else {
7.46 - scroll = (ScrollPane) container.getCenter();
7.47 - }
7.48 - scroll.setPrefViewportWidth( width );
7.49 - scroll.setPrefViewportHeight(height );
7.50 - webView.setMaxWidth( width );
7.51 - webView.setMaxHeight( height );
7.52 - webView.setMinWidth( width );
7.53 - webView.setMinHeight( height );
7.54 + private void _resize(final double width, final double height) {
7.55 + Window window = container.getScene().getWindow();
7.56 + // size difference between root node and window depends on OS and Decorations
7.57 + double diffY = window.getHeight() - container.getHeight();
7.58 + double diffX = window.getWidth() - container.getWidth();
7.59 +
7.60 + webView.setMaxWidth(width);
7.61 + webView.setMaxHeight(height);
7.62 + webView.setMinWidth(width);
7.63 + webView.setMinHeight(height);
7.64 + javafx.geometry.Rectangle2D screenBounds = Screen.getPrimary().getBounds();
7.65 + double scaleX = screenBounds.getWidth() / ( width + diffX );
7.66 + double scaleY = screenBounds.getHeight() / ( height + diffY );
7.67 + // calculate scale factor if too big for device, the .1 adds some padding
7.68 + double scale = Math.min(Math.min(scaleX, scaleY), 1.1) - .1;
7.69 + webView.setScaleX(scale);
7.70 + webView.setScaleY(scale);
7.71 + container.getScene().setRoot(new Group());
7.72 + ((Stage)window).setScene(new Scene(container, width * scale, height * scale));
7.73 }
7.74
7.75 private void _autofit() {
8.1 --- a/boot/pom.xml Tue Dec 09 07:23:22 2014 +0100
8.2 +++ b/boot/pom.xml Tue Dec 09 08:33:22 2014 +0100
8.3 @@ -36,6 +36,8 @@
8.4 <groupId>org.ow2.asm</groupId>
8.5 <artifactId>asm</artifactId>
8.6 <type>jar</type>
8.7 + <scope>provided</scope>
8.8 + <optional>true</optional>
8.9 </dependency>
8.10 <dependency>
8.11 <groupId>org.testng</groupId>
9.1 --- a/boot/src/main/java/net/java/html/boot/BrowserBuilder.java Tue Dec 09 07:23:22 2014 +0100
9.2 +++ b/boot/src/main/java/net/java/html/boot/BrowserBuilder.java Tue Dec 09 08:33:22 2014 +0100
9.3 @@ -63,7 +63,9 @@
9.4 import net.java.html.BrwsrCtx;
9.5 import net.java.html.js.JavaScriptBody;
9.6 import org.netbeans.html.boot.spi.Fn;
9.7 +import org.netbeans.html.boot.spi.Fn.Presenter;
9.8 import org.netbeans.html.context.spi.Contexts;
9.9 +import org.netbeans.html.context.spi.Contexts.Id;
9.10 import org.netbeans.html.boot.impl.FindResources;
9.11 import org.netbeans.html.boot.impl.FnContext;
9.12 import org.netbeans.html.boot.impl.FnUtils;
9.13 @@ -120,6 +122,15 @@
9.14 /** Entry method to obtain a new browser builder. Follow by calling
9.15 * its instance methods like {@link #loadClass(java.lang.Class)} and
9.16 * {@link #loadPage(java.lang.String)}.
9.17 + * Since introduction of {@link Id technology identifiers} the
9.18 + * provided <code>context</code> objects are also passed to the
9.19 + * {@link BrwsrCtx context} when it is being
9.20 + * {@link Contexts#newBuilder(java.lang.Object...) created}
9.21 + * and can influence the selection
9.22 + * of available technologies
9.23 + * (like {@link org.netbeans.html.json.spi.Technology},
9.24 + * {@link org.netbeans.html.json.spi.Transfer} or
9.25 + * {@link org.netbeans.html.json.spi.WSTransfer}) by name.
9.26 *
9.27 * @param context any instances that should be available to the builder -
9.28 * implementation dependant
9.29 @@ -210,7 +221,7 @@
9.30 }
9.31
9.32 /** Loader to use when searching for classes to initialize.
9.33 - * If specified, this loader is going to be used to load {@link Fn.Presenter}
9.34 + * If specified, this loader is going to be used to load {@link Presenter}
9.35 * and {@link Contexts#fillInByProviders(java.lang.Class, org.netbeans.html.context.spi.Contexts.Builder) fill} {@link BrwsrCtx} in.
9.36 * Specifying special classloader may be useful in modular systems,
9.37 * like OSGi, where one needs to load classes from many otherwise independent
9.38 @@ -272,13 +283,16 @@
9.39
9.40 final ClassLoader activeLoader;
9.41 if (loader != null) {
9.42 - if (!FnUtils.isJavaScriptCapable(loader)) {
9.43 + if (!FnContext.isJavaScriptCapable(loader)) {
9.44 throw new IllegalStateException("Loader cannot resolve @JavaScriptBody: " + loader);
9.45 }
9.46 activeLoader = loader;
9.47 - } else if (FnUtils.isJavaScriptCapable(myCls.getClassLoader())) {
9.48 + } else if (FnContext.isJavaScriptCapable(myCls.getClassLoader())) {
9.49 activeLoader = myCls.getClassLoader();
9.50 } else {
9.51 + if (!FnContext.isAsmPresent()) {
9.52 + throw new IllegalStateException("Cannot find asm-5.0.jar classes!");
9.53 + }
9.54 FImpl impl = new FImpl(myCls.getClassLoader());
9.55 activeLoader = FnUtils.newLoader(impl, dfnr, myCls.getClassLoader().getParent());
9.56 }
9.57 @@ -297,7 +311,7 @@
9.58 if (browserClass != null) {
9.59 browserClass[0] = newClazz;
9.60 }
9.61 - Contexts.Builder cb = Contexts.newBuilder();
9.62 + Contexts.Builder cb = Contexts.newBuilder(context);
9.63 if (!Contexts.fillInByProviders(newClazz, cb)) {
9.64 LOG.log(Level.WARNING, "Using empty technology for {0}", newClazz);
9.65 }
10.1 --- a/boot/src/main/java/net/java/html/js/package.html Tue Dec 09 07:23:22 2014 +0100
10.2 +++ b/boot/src/main/java/net/java/html/js/package.html Tue Dec 09 08:33:22 2014 +0100
10.3 @@ -197,7 +197,41 @@
10.4 passing of arrays works OK. It is however good to keep it in mind to
10.5 avoid unwanted surprises.
10.6
10.7 + <h3>Instance Reference to JavaScript Object</h3>
10.8 +
10.9 + When writing wrappers around existing JavaScript libraries, it may be
10.10 + useful to hold a reference to some JavaScript object from a Java
10.11 + instance and use it later.
10.12 +<pre>
10.13 +<b>class</b> WrapperAroundJsObj {
10.14 + <b>private final</b> Object js;
10.15 +
10.16 + WrapperAroundJsObj() {
10.17 + js = initValue();
10.18 + }
10.19 +
10.20 + <b>public void</b> set(int v) {
10.21 + setValue(js, v);
10.22 + }
10.23 +
10.24 + {@link net.java.html.js.JavaScriptBody @JavaScriptBody}(args = {}, body = "return { value : 0 };")
10.25 + <b>private static native</b> Object initValue();
10.26 +
10.27 + {@link net.java.html.js.JavaScriptBody @JavaScriptBody}(
10.28 + args = { "js", "v" }, body = "js.value = v;", wait4js = false
10.29 + )
10.30 + <b>private static native void</b> setValue(Object js, int v);
10.31 +}
10.32 +</pre>
10.33 + The type of the Java reference is {@link java.lang.Object}.
10.34 + From a Java perspective it has no additional methods or fields, however
10.35 + its properties can be manipulated from JavaScript. Send the object back
10.36 + to JavaScript by passing it as a parameter of some method
10.37 + (like the <code>setValue</code> one) and perform necessary JavaScript
10.38 + calls or changes on it.
10.39 +
10.40 <h3>Post Process Classes</h3>
10.41 + <a name="post-process"></a>
10.42
10.43 Classes with {@link net.java.html.js.JavaScriptBody} annotated methods need to
10.44 be post processed before they can be used - e.g. their <code>native</code>
10.45 @@ -257,7 +291,9 @@
10.46 will create a special classloader to that does the processing before
10.47 loading the bytecode into the virtual machine.
10.48 <p></p>
10.49 - The options are rich, however to avoid any troubles, it is recommended
10.50 + The options are rich, however to avoid any troubles (as the runtime
10.51 + processing needs to also include <code>asm-5.0.jar</code> on application
10.52 + classpath), it is recommended
10.53 to perform the <b>compile time</b> processing.
10.54
10.55 <h3>Getting Started</h3>
11.1 --- a/boot/src/main/java/org/netbeans/html/boot/impl/FnContext.java Tue Dec 09 07:23:22 2014 +0100
11.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/FnContext.java Tue Dec 09 08:33:22 2014 +0100
11.3 @@ -45,8 +45,10 @@
11.4 import java.io.Closeable;
11.5 import java.io.Flushable;
11.6 import java.io.IOException;
11.7 +import java.util.logging.Level;
11.8 import java.util.logging.Logger;
11.9 import org.netbeans.html.boot.spi.Fn;
11.10 +import org.objectweb.asm.Opcodes;
11.11
11.12 /**
11.13 *
11.14 @@ -60,6 +62,33 @@
11.15 DUMMY.prev = DUMMY;
11.16 }
11.17
11.18 + public static boolean isJavaScriptCapable(ClassLoader l) {
11.19 + if (l instanceof JsClassLoader) {
11.20 + return true;
11.21 + }
11.22 + if (l.getResource("META-INF/net.java.html.js.classes") != null) {
11.23 + return false;
11.24 + }
11.25 + return true;
11.26 + }
11.27 +
11.28 + public static boolean isAsmPresent() {
11.29 + Throwable t;
11.30 + try {
11.31 + Class.forName(Opcodes.class.getName());
11.32 + return true;
11.33 + } catch (LinkageError ex) {
11.34 + t = ex;
11.35 + } catch (ClassNotFoundException ex) {
11.36 + t = ex;
11.37 + }
11.38 + LOG.log(Level.SEVERE, "When using @JavaScriptBody methods, one needs to either:");
11.39 + LOG.log(Level.SEVERE, " - include asm-5.0.jar on runtime classpath");
11.40 + LOG.log(Level.SEVERE, " - post process classes, see http://bits.netbeans.org/html+java/dev/net/java/html/js/package-summary.html#post-process");
11.41 + LOG.log(Level.SEVERE, "Cannot initialize asm-5.0.jar!", t);
11.42 + return false;
11.43 + }
11.44 +
11.45 private Object prev;
11.46 private final Fn.Presenter current;
11.47 private FnContext(Fn.Presenter prevP, Fn.Presenter newP) {
12.1 --- a/boot/src/main/java/org/netbeans/html/boot/impl/FnUtils.java Tue Dec 09 07:23:22 2014 +0100
12.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/FnUtils.java Tue Dec 09 08:33:22 2014 +0100
12.3 @@ -108,16 +108,6 @@
12.4 return bytecode;
12.5 }
12.6
12.7 - public static boolean isJavaScriptCapable(ClassLoader l) {
12.8 - if (l instanceof JsClassLoader) {
12.9 - return true;
12.10 - }
12.11 - if (l.getResource("META-INF/net.java.html.js.classes") != null) {
12.12 - return false;
12.13 - }
12.14 - return true;
12.15 - }
12.16 -
12.17 public static boolean isValid(Fn fn) {
12.18 return fn != null && fn.isValid();
12.19 }
13.1 --- a/context/src/main/java/net/java/html/BrwsrCtx.java Tue Dec 09 07:23:22 2014 +0100
13.2 +++ b/context/src/main/java/net/java/html/BrwsrCtx.java Tue Dec 09 08:33:22 2014 +0100
13.3 @@ -47,6 +47,7 @@
13.4 import org.netbeans.html.context.impl.CtxAccssr;
13.5 import org.netbeans.html.context.impl.CtxImpl;
13.6 import org.netbeans.html.context.spi.Contexts;
13.7 +import org.netbeans.html.context.spi.Contexts.Id;
13.8
13.9 /** Represents context where the <code>net.java.html.json.Model</code>
13.10 * and other objects
13.11 @@ -54,7 +55,12 @@
13.12 * The context is also associated with the actual HTML technology
13.13 * in the HTML page - there is likely to be different context for
13.14 * <a href="http://knockoutjs.com">knockout.js</a> and different one
13.15 - * for <a href="http://angularjs.org">angular</a>.
13.16 + * for <a href="http://angularjs.org">angular</a>. Since version 1.1
13.17 + * the content of contexts can be selected by registering
13.18 + * implementations under specific
13.19 + * {@link Id technology identifiers} and requesting them during
13.20 + * {@link Contexts#newBuilder(java.lang.Object...) construction} of the
13.21 + * context.
13.22 *
13.23 * @author Jaroslav Tulach
13.24 */
14.1 --- a/context/src/main/java/org/netbeans/html/context/impl/CtxImpl.java Tue Dec 09 07:23:22 2014 +0100
14.2 +++ b/context/src/main/java/org/netbeans/html/context/impl/CtxImpl.java Tue Dec 09 08:33:22 2014 +0100
14.3 @@ -44,8 +44,10 @@
14.4
14.5 import java.util.ArrayList;
14.6 import java.util.Collections;
14.7 +import java.util.Comparator;
14.8 import java.util.List;
14.9 import net.java.html.BrwsrCtx;
14.10 +import org.netbeans.html.context.spi.Contexts;
14.11
14.12 /** Implementation detail. Holds list of technologies for particular
14.13 * {@link BrwsrCtx}.
14.14 @@ -54,13 +56,15 @@
14.15 */
14.16 public final class CtxImpl {
14.17 private final List<Bind<?>> techs;
14.18 + private final Object[] context;
14.19
14.20 - public CtxImpl() {
14.21 - techs = new ArrayList<Bind<?>>();
14.22 + public CtxImpl(Object[] context) {
14.23 + this(context, new ArrayList<Bind<?>>());
14.24 }
14.25
14.26 - private CtxImpl(List<Bind<?>> techs) {
14.27 + private CtxImpl(Object[] context, List<Bind<?>> techs) {
14.28 this.techs = techs;
14.29 + this.context = context;
14.30 }
14.31
14.32 public static <Tech> Tech find(BrwsrCtx context, Class<Tech> technology) {
14.33 @@ -74,9 +78,9 @@
14.34 }
14.35
14.36 public BrwsrCtx build() {
14.37 - Collections.sort(techs);
14.38 + Collections.sort(techs, new BindCompare());
14.39 final List<Bind<?>> arr = Collections.unmodifiableList(techs);
14.40 - CtxImpl impl = new CtxImpl(arr);
14.41 + CtxImpl impl = new CtxImpl(context, arr);
14.42 BrwsrCtx ctx = CtxAccssr.getDefault().newContext(impl);
14.43 return ctx;
14.44 }
14.45 @@ -85,7 +89,7 @@
14.46 techs.add(new Bind<Tech>(type, impl, priority));
14.47 }
14.48
14.49 - private static final class Bind<Tech> implements Comparable<Bind<?>> {
14.50 + private static final class Bind<Tech> {
14.51 private final Class<Tech> clazz;
14.52 private final Tech impl;
14.53 private final int priority;
14.54 @@ -97,16 +101,39 @@
14.55 }
14.56
14.57 @Override
14.58 - public int compareTo(Bind<?> o) {
14.59 - if (priority != o.priority) {
14.60 - return priority - o.priority;
14.61 - }
14.62 - return clazz.getName().compareTo(o.clazz.getName());
14.63 - }
14.64 -
14.65 - @Override
14.66 public String toString() {
14.67 return "Bind{" + "clazz=" + clazz + "@" + clazz.getClassLoader() + ", impl=" + impl + ", priority=" + priority + '}';
14.68 }
14.69 }
14.70 +
14.71 + private final class BindCompare implements Comparator<Bind<?>> {
14.72 + boolean isPrefered(Bind<?> b) {
14.73 + final Class<?> implClazz = b.impl.getClass();
14.74 + Contexts.Id id = implClazz.getAnnotation(Contexts.Id.class);
14.75 + if (id == null) {
14.76 + return false;
14.77 + }
14.78 + for (String v : id.value()) {
14.79 + for (Object c : context) {
14.80 + if (v.equals(c)) {
14.81 + return true;
14.82 + }
14.83 + }
14.84 + }
14.85 + return false;
14.86 + }
14.87 +
14.88 + @Override
14.89 + public int compare(Bind<?> o1, Bind<?> o2) {
14.90 + boolean p1 = isPrefered(o1);
14.91 + boolean p2 = isPrefered(o2);
14.92 + if (p1 != p2) {
14.93 + return p1 ? -1 : 1;
14.94 + }
14.95 + if (o1.priority != o2.priority) {
14.96 + return o1.priority - o2.priority;
14.97 + }
14.98 + return o1.clazz.getName().compareTo(o2.clazz.getName());
14.99 + }
14.100 + } // end of BindCompare
14.101 }
15.1 --- a/context/src/main/java/org/netbeans/html/context/spi/Contexts.java Tue Dec 09 07:23:22 2014 +0100
15.2 +++ b/context/src/main/java/org/netbeans/html/context/spi/Contexts.java Tue Dec 09 08:33:22 2014 +0100
15.3 @@ -42,6 +42,10 @@
15.4 */
15.5 package org.netbeans.html.context.spi;
15.6
15.7 +import java.lang.annotation.ElementType;
15.8 +import java.lang.annotation.Retention;
15.9 +import java.lang.annotation.RetentionPolicy;
15.10 +import java.lang.annotation.Target;
15.11 import java.util.ServiceLoader;
15.12 import net.java.html.BrwsrCtx;
15.13 import org.netbeans.html.context.impl.CtxImpl;
15.14 @@ -59,11 +63,23 @@
15.15
15.16 /** Creates new, empty builder for creation of {@link BrwsrCtx}. At the
15.17 * end call the {@link Builder#build()} method to generate the context.
15.18 - *
15.19 + *
15.20 + * @param context instances of various classes or names of {@link Id technologies}
15.21 + * to be preferred and used in the built {@link BrwsrCtx context}.
15.22 + * @return new instance of the builder
15.23 + * @since 1.1
15.24 + */
15.25 + public static Builder newBuilder(Object... context) {
15.26 + return new Builder(context);
15.27 + }
15.28 + /** Creates new, empty builder for creation of {@link BrwsrCtx}. At the
15.29 + * end call the {@link Builder#build()} method to generate the context.
15.30 + * Simply calls {@link #newBuilder(java.lang.Object...) newBuilder(new Object[0])}.
15.31 + *
15.32 * @return new instance of the builder
15.33 */
15.34 public static Builder newBuilder() {
15.35 - return new Builder();
15.36 + return newBuilder(new Object[0]);
15.37 }
15.38
15.39 /** Seeks for the specified technology in the provided context.
15.40 @@ -118,6 +134,23 @@
15.41 }
15.42 return found;
15.43 }
15.44 +
15.45 + /** Identifies the technologies passed to {@link Builder context builder}
15.46 + * by a name. Each implementation of a technology
15.47 + * {@link Builder#register(java.lang.Class, java.lang.Object, int) registered into a context}
15.48 + * can be annotated with a name (or multiple names). Such implementation
15.49 + * will later be
15.50 + * {@link Contexts#fillInByProviders(java.lang.Class, org.netbeans.html.context.spi.Contexts.Builder) preferred during lookup}
15.51 + * if their name(s) has been requested in when
15.52 + * {@link Contexts#newBuilder(java.lang.Object...) creating a context}.
15.53 + * @since 1.1
15.54 + */
15.55 + @Retention(RetentionPolicy.RUNTIME)
15.56 + @Target(ElementType.TYPE)
15.57 + public @interface Id {
15.58 + /** Identifier(s) for the implementation. */
15.59 + public String[] value();
15.60 + }
15.61
15.62 /** Implementors of various HTML technologies should
15.63 * register their implementation via <code>org.openide.util.lookup.ServiceProvider</code>, so
15.64 @@ -152,9 +185,10 @@
15.65 * @author Jaroslav Tulach
15.66 */
15.67 public static final class Builder {
15.68 - private final CtxImpl impl = new CtxImpl();
15.69 + private final CtxImpl impl;
15.70
15.71 - Builder() {
15.72 + public Builder(Object[] context) {
15.73 + this.impl = new CtxImpl(context);
15.74 }
15.75
15.76 /** Registers new technology into the context. Each technology is
16.1 --- a/context/src/test/java/net/java/html/BrwsrCtxTest.java Tue Dec 09 07:23:22 2014 +0100
16.2 +++ b/context/src/test/java/net/java/html/BrwsrCtxTest.java Tue Dec 09 08:33:22 2014 +0100
16.3 @@ -44,6 +44,7 @@
16.4
16.5 import org.netbeans.html.context.spi.Contexts;
16.6 import static org.testng.Assert.*;
16.7 +import org.testng.annotations.Test;
16.8
16.9 /**
16.10 *
16.11 @@ -72,4 +73,48 @@
16.12 assertTrue(arr[0], "Runnable was executed");
16.13 }
16.14
16.15 +
16.16 + @Test public void defaultOrderOfRegistrations() {
16.17 + BrwsrCtx ctx = registerRs(Contexts.newBuilder());
16.18 + Class<? extends Runnable> clazz = Contexts.find(ctx, Runnable.class).getClass();
16.19 + assertEquals(clazz, R1.class, "R1 is registered at value 10");
16.20 + }
16.21 +
16.22 + @Test public void preferOne() {
16.23 + BrwsrCtx ctx = registerRs(Contexts.newBuilder("one"));
16.24 + Class<? extends Runnable> clazz = Contexts.find(ctx, Runnable.class).getClass();
16.25 + assertEquals(clazz, R1.class, "R1 is registered at value 10");
16.26 + }
16.27 +
16.28 + @Test public void preferTwo() {
16.29 + BrwsrCtx ctx = registerRs(Contexts.newBuilder("two"));
16.30 + Class<? extends Runnable> clazz = Contexts.find(ctx, Runnable.class).getClass();
16.31 + assertEquals(clazz, R2.class, "R2 is preferred");
16.32 + }
16.33 +
16.34 + @Test public void preferBoth() {
16.35 + BrwsrCtx ctx = registerRs(Contexts.newBuilder("one", "two"));
16.36 + Class<? extends Runnable> clazz = Contexts.find(ctx, Runnable.class).getClass();
16.37 + assertEquals(clazz, R1.class, "R1 is registered at value 10");
16.38 + }
16.39 +
16.40 + private static BrwsrCtx registerRs(Contexts.Builder b) {
16.41 + b.register(Runnable.class, new R1(), 10);
16.42 + b.register(Runnable.class, new R2(), 20);
16.43 + return b.build();
16.44 + }
16.45 +
16.46 + @Contexts.Id("one")
16.47 + static final class R1 implements Runnable {
16.48 + @Override
16.49 + public void run() {
16.50 + }
16.51 + }
16.52 + @Contexts.Id("two")
16.53 + static final class R2 implements Runnable {
16.54 + @Override
16.55 + public void run() {
16.56 + }
16.57 + }
16.58 +
16.59 }
16.60 \ No newline at end of file
17.1 --- a/geo/src/main/java/org/netbeans/html/geo/spi/GLProvider.java Tue Dec 09 07:23:22 2014 +0100
17.2 +++ b/geo/src/main/java/org/netbeans/html/geo/spi/GLProvider.java Tue Dec 09 08:33:22 2014 +0100
17.3 @@ -47,7 +47,7 @@
17.4 import net.java.html.geo.Position;
17.5 import net.java.html.geo.Position.Handle;
17.6 import net.java.html.geo.Position.Coordinates;
17.7 -import org.netbeans.html.context.spi.Contexts;
17.8 +import org.netbeans.html.context.spi.Contexts.Builder;
17.9 import org.netbeans.html.geo.impl.Accessor;
17.10 import org.openide.util.lookup.ServiceProvider;
17.11
17.12 @@ -55,7 +55,7 @@
17.13 * Subclass this class, implement its method and register it into the system.
17.14 * You can either use {@link ServiceProvider} to register globally, or
17.15 * one can register into {@link BrwsrCtx} (via
17.16 - * {@link Contexts.Builder#register(java.lang.Class, java.lang.Object, int) context builder}).
17.17 + * {@link Builder#register(java.lang.Class, java.lang.Object, int) context builder}).
17.18 * <p>
17.19 * There is default system provider (used as a fallback) based on
17.20 * <a href="http://www.w3.org/TR/geolocation-API/">
17.21 @@ -93,11 +93,11 @@
17.22 * </pre>
17.23 *
17.24 * @author Jaroslav Tulach
17.25 - * @param <Watch> your choosen type to represent one query (one time) or watch (repeated) request -
17.26 + * @param <Watch> your chosen type to represent one query (one time) or watch (repeated) request -
17.27 * this type is used in {@link #start(org.netbeans.html.geo.spi.GLProvider.Query) start}
17.28 * and {@link #stop(java.lang.Object) stop} methods.
17.29 *
17.30 - * @param <Coords> your choosen type to represent geolocation coordinates -
17.31 + * @param <Coords> your chosen type to represent geolocation coordinates -
17.32 * use in many methods in this class like {@link #latitude(java.lang.Object)} and
17.33 * {@link #longitude(java.lang.Object)}.
17.34 *
17.35 @@ -263,7 +263,7 @@
17.36
17.37 /**
17.38 * Is this one time or repeated request? Mimics value provided in
17.39 - * {@link Handle#Handle(boolean) constructor}.
17.40 + * {@link Handle constructor}.
17.41 *
17.42 * @return true if this is one time request, false if the request is
17.43 * permanent (up until {@link Handle#stop() } is called).
18.1 --- a/json-tck/src/main/java/org/netbeans/html/json/tck/KnockoutTCK.java Tue Dec 09 07:23:22 2014 +0100
18.2 +++ b/json-tck/src/main/java/org/netbeans/html/json/tck/KnockoutTCK.java Tue Dec 09 08:33:22 2014 +0100
18.3 @@ -55,6 +55,7 @@
18.4 import net.java.html.json.tests.WebSocketTest;
18.5 import org.netbeans.html.context.spi.Contexts.Builder;
18.6 import org.openide.util.lookup.ServiceProvider;
18.7 +import org.testng.annotations.Factory;
18.8
18.9 /** Entry point for providers of different HTML binding technologies (like
18.10 * Knockout.js in JavaFX's WebView). Sample usage:
18.11 @@ -67,7 +68,7 @@
18.12 // use {@link Builder}.{@link Builder#build() build}();
18.13 }
18.14
18.15 - {@code @}{@link org.testng.annotations.Factory} public static Object[] create() {
18.16 + {@code @}{@link Factory} public static Object[] create() {
18.17 return VMTest.newTests().withClasses({@link KnockoutTCK#testClasses}()).build();
18.18 }
18.19 }
19.1 --- a/json/src/main/java/net/java/html/json/Model.java Tue Dec 09 07:23:22 2014 +0100
19.2 +++ b/json/src/main/java/net/java/html/json/Model.java Tue Dec 09 08:33:22 2014 +0100
19.3 @@ -50,19 +50,19 @@
19.4 import java.util.List;
19.5
19.6 /** Defines a model class that represents a single
19.7 - * <a href="http://en.wikipedia.org/wiki/JSON">JSON</a>-like object
19.8 + * <a target="_blank" href="http://en.wikipedia.org/wiki/JSON">JSON</a>-like object
19.9 * named {@link #className()}. The generated class contains
19.10 * getters and setters for properties defined via {@link #properties()} and
19.11 * getters for other, derived properties defined by annotating methods
19.12 * of this class by {@link ComputedProperty}. Each property
19.13 * can be of primitive type, an {@link Enum enum type} or (in order to create
19.14 - * nested <a href="http://en.wikipedia.org/wiki/JSON">JSON</a> structure)
19.15 + * nested <a target="_blank" href="http://en.wikipedia.org/wiki/JSON">JSON</a> structure)
19.16 * of another {@link Model class generated by @Model} annotation. Each property
19.17 * can either represent a single value or be an array of its values.
19.18 * <p>
19.19 * The {@link #className() generated class}'s <code>toString</code> method
19.20 * converts the state of the object into
19.21 - * <a href="http://en.wikipedia.org/wiki/JSON">JSON</a> format. One can
19.22 + * <a target="_blank" href="http://en.wikipedia.org/wiki/JSON">JSON</a> format. One can
19.23 * use {@link Models#parse(net.java.html.BrwsrCtx, java.lang.Class, java.io.InputStream)}
19.24 * method to read the JSON text stored in a file or other stream back into the Java model.
19.25 * One can also use {@link OnReceive @OnReceive} annotation to read the model
19.26 @@ -109,7 +109,7 @@
19.27 * <b>new</b> Address("Markoušovice", "Úpice"),
19.28 * <b>new</b> Address("V Parku", "Praha")
19.29 * );
19.30 - * // p.toString() then returns equivalent of following <a href="http://en.wikipedia.org/wiki/JSON">JSON</a> object
19.31 + * // p.toString() then returns equivalent of following <a target="_blank" href="http://en.wikipedia.org/wiki/JSON">JSON</a> object
19.32 * {
19.33 * "firstName" : "Jaroslav",
19.34 * "lastName" : "Tulach",
19.35 @@ -120,10 +120,10 @@
19.36 * }
19.37 * </pre>
19.38 * <p>
19.39 - * In case you are using <a href="http://knockoutjs.com/">Knockout technology</a>
19.40 + * In case you are using <a target="_blank" href="http://knockoutjs.com/">Knockout technology</a>
19.41 * for Java then you can associate such model object with surrounding HTML page by
19.42 * calling: <code>p.applyBindings();</code>. The page can then use regular
19.43 - * <a href="http://knockoutjs.com/">Knockout</a> bindings to reference your
19.44 + * <a target="_blank" href="http://knockoutjs.com/">Knockout</a> bindings to reference your
19.45 * model and create dynamic connection between your model in Java and
19.46 * live DOM structure in the browser:
19.47 * <pre>
19.48 @@ -132,7 +132,58 @@
19.49 * Lives in <span data-bind="text: town"/>
19.50 * </div>
19.51 * </pre>
19.52 - * <p>
19.53 + *
19.54 + * <h4>Access Raw <a target="_blank" href="http://knockoutjs.com/">Knockout</a> Observables</h4>
19.55 + *
19.56 + * One can obtain <quote>raw</quote> JavaScript object representing the
19.57 + * instance of {@link Model model class} (with appropriate
19.58 + * <a target="_blank" href="http://knockoutjs.com/">Knockout</a> <b>observable</b> properties)
19.59 + * by calling {@link Models#toRaw(java.lang.Object) Models.toRaw(p)}. For
19.60 + * example here is a way to obtain the value of <code>fullName</code> property
19.61 + * (inefficient as it switches between Java and JavaScript back and forth,
19.62 + * but functional and instructive) via a JavaScript call:
19.63 + * <pre>
19.64 + * {@link net.java.html.js.JavaScriptBody @JavaScriptBody}(args = "raw", javacall = true, body =
19.65 + * "return raw.fullName();" // yes, the <a target="_blank" href="http://knockoutjs.com/">Knockout</a> property is a function
19.66 + * )
19.67 + * static native String jsFullName(Object raw);
19.68 + * // and later
19.69 + * Person p = ...;
19.70 + * String fullName = jsFullName({@link Models#toRaw(java.lang.Object) Models.toRaw(p)});
19.71 + * </pre>
19.72 + * The above shows how to read a value from <a target="_blank" href="http://knockoutjs.com/">Knockout</a>
19.73 + * observable. There is a way to change the value too:
19.74 + * One can pass a parameter to the property-function and then
19.75 + * it acts like a setter (of course not in the case of read only <code>fullName</code> property,
19.76 + * but for <code>firstName</code> or <code>lastName</code> the setter is
19.77 + * available). Everything mentioned in this paragraph applies only when
19.78 + * <a target="_blank" href="http://knockoutjs.com/">Knockout</a> technology is active
19.79 + * other technologies may behave differently.
19.80 + *
19.81 + * <h4>Copy to Plain JSON</h4>
19.82 + * There is a way to pass a value of a Java {@link Model model class} instance
19.83 + * by copy and convert
19.84 + * the {@link Model the whole object} into plain
19.85 + * <a target="_blank" href="http://en.wikipedia.org/wiki/JSON">JSON</a>. Just
19.86 + * print it as a string and parse it in JavaScript:
19.87 + * <pre>
19.88 + * {@link net.java.html.js.JavaScriptBody @JavaScriptBody}(args = { "txt" }, body =
19.89 + * "return JSON.parse(txt);"
19.90 + * )
19.91 + * private static native Object parseJSON(String txt);
19.92 + *
19.93 + * public static Object toPlainJSON(Object model) {
19.94 + * return parseJSON(model.toString());
19.95 + * }
19.96 + * </pre>
19.97 + * The newly returned instance is a one time copy of the original model and is no longer
19.98 + * connected to it. The copy based behavior is independent on any
19.99 + * particular technology and should work
19.100 + * in <a target="_blank" href="http://knockoutjs.com/">Knockout</a> as well as other
19.101 + * technology implementations.
19.102 + *
19.103 + * <h4>References</h4>
19.104 + *
19.105 * Visit an <a target="_blank" href="http://dew.apidesign.org/dew/#7510833">on-line demo</a>
19.106 * to see a histogram driven by the {@link Model} annotation or try
19.107 * a little <a target="_blank" href="http://dew.apidesign.org/dew/#7263102">math test</a>.
20.1 --- a/json/src/main/java/org/netbeans/html/json/spi/Technology.java Tue Dec 09 07:23:22 2014 +0100
20.2 +++ b/json/src/main/java/org/netbeans/html/json/spi/Technology.java Tue Dec 09 08:33:22 2014 +0100
20.3 @@ -45,10 +45,17 @@
20.4 import net.java.html.BrwsrCtx;
20.5 import net.java.html.json.Model;
20.6 import net.java.html.json.Models;
20.7 +import org.netbeans.html.context.spi.Contexts.Id;
20.8
20.9 /** An implementation of a binding between model classes (see {@link Model})
20.10 * and particular technology like <a href="http://knockoutjs.com">knockout.js</a>
20.11 * in a browser window, etc.
20.12 + * Since introduction of {@link Id technology identifiers} one can choose between
20.13 + * different background implementations to handle the conversion and
20.14 + * communication requests. The currently known provider is
20.15 + * <code>org.netbeans.html:ko4j</code> module which registers
20.16 + * a <a href="http://knockoutjs.com" target="_blank">knockout.js</a>
20.17 + * implementation called <b>ko4j</b>.
20.18 *
20.19 * @author Jaroslav Tulach
20.20 */
21.1 --- a/json/src/main/java/org/netbeans/html/json/spi/Transfer.java Tue Dec 09 07:23:22 2014 +0100
21.2 +++ b/json/src/main/java/org/netbeans/html/json/spi/Transfer.java Tue Dec 09 08:33:22 2014 +0100
21.3 @@ -45,9 +45,17 @@
21.4 import java.io.IOException;
21.5 import java.io.InputStream;
21.6 import org.netbeans.html.context.spi.Contexts.Builder;
21.7 +import org.netbeans.html.context.spi.Contexts.Id;
21.8
21.9 /** A {@link Builder service provider interface} responsible for
21.10 * conversion of JSON objects to Java ones and vice-versa.
21.11 + * Since introduction of {@link Id technology identifiers} one can choose between
21.12 + * different background implementations to handle the conversion and
21.13 + * communication requests. The known providers include
21.14 + * <code>org.netbeans.html:ko4j</code> module which registers
21.15 + * a native browser implementation called <b>xhr</b>, and a
21.16 + * <code>org.netbeans.html:ko-ws-tyrus</code> module which registers
21.17 + * Java based implementation named <b>tyrus</b>.
21.18 *
21.19 * @author Jaroslav Tulach
21.20 */
22.1 --- a/json/src/main/java/org/netbeans/html/json/spi/WSTransfer.java Tue Dec 09 07:23:22 2014 +0100
22.2 +++ b/json/src/main/java/org/netbeans/html/json/spi/WSTransfer.java Tue Dec 09 08:33:22 2014 +0100
22.3 @@ -44,9 +44,17 @@
22.4
22.5 import net.java.html.BrwsrCtx;
22.6 import org.netbeans.html.context.spi.Contexts.Provider;
22.7 +import org.netbeans.html.context.spi.Contexts.Id;
22.8
22.9 /** Interface for providers of WebSocket protocol. Register into a
22.10 - * {@link BrwsrCtx context} in your own {@link Provider}
22.11 + * {@link BrwsrCtx context} in your own {@link Provider}.
22.12 + * Since introduction of {@link Id technology identifiers} one can choose between
22.13 + * different background implementations to handle the conversion and
22.14 + * communication requests. The known providers include
22.15 + * <code>org.netbeans.html:ko4j</code> module which registers
22.16 + * a native browser implementation called <b>websocket</b>, and a
22.17 + * <code>org.netbeans.html:ko-ws-tyrus</code> module which registers
22.18 + * Java based implementation named <b>tyrus</b>.
22.19 *
22.20 * @author Jaroslav Tulach
22.21 * @param <WebSocket> internal implementation type representing the socket
23.1 --- a/json/src/test/java/net/java/html/json/MapModelTest.java Tue Dec 09 07:23:22 2014 +0100
23.2 +++ b/json/src/test/java/net/java/html/json/MapModelTest.java Tue Dec 09 08:33:22 2014 +0100
23.3 @@ -47,6 +47,8 @@
23.4 import java.io.InputStream;
23.5 import java.lang.reflect.InvocationTargetException;
23.6 import java.util.HashMap;
23.7 +import java.util.Iterator;
23.8 +import java.util.ListIterator;
23.9 import java.util.Map;
23.10 import org.netbeans.html.context.spi.Contexts;
23.11 import org.netbeans.html.json.spi.FunctionBinding;
23.12 @@ -179,6 +181,62 @@
23.13
23.14 assertEquals(p.getSex(), Sex.FEMALE, "Changed");
23.15 }
23.16 +
23.17 + @Test public void removeViaIterator() {
23.18 + People p = Models.bind(new People(), c);
23.19 + p.getNicknames().add("One");
23.20 + p.getNicknames().add("Two");
23.21 + p.getNicknames().add("Three");
23.22 +
23.23 + Map m = (Map)Models.toRaw(p);
23.24 + Object o = m.get("nicknames");
23.25 + assertNotNull(o, "List registered in the model");
23.26 + assertEquals(o.getClass(), One.class);
23.27 + One one = (One)o;
23.28 +
23.29 +
23.30 + assertEquals(one.changes, 0, "No change");
23.31 +
23.32 + Iterator<String> it = p.getNicknames().iterator();
23.33 + assertEquals(it.next(), "One");
23.34 + assertEquals(it.next(), "Two");
23.35 + it.remove();
23.36 + assertEquals(it.next(), "Three");
23.37 + assertFalse(it.hasNext());
23.38 +
23.39 +
23.40 + assertEquals(one.changes, 1, "One change");
23.41 + }
23.42 +
23.43 + @Test public void removeViaListIterator() {
23.44 + People p = Models.bind(new People(), c);
23.45 + p.getNicknames().add("One");
23.46 + p.getNicknames().add("Two");
23.47 + p.getNicknames().add("Three");
23.48 +
23.49 + Map m = (Map)Models.toRaw(p);
23.50 + Object o = m.get("nicknames");
23.51 + assertNotNull(o, "List registered in the model");
23.52 + assertEquals(o.getClass(), One.class);
23.53 + One one = (One)o;
23.54 +
23.55 +
23.56 + assertEquals(one.changes, 0, "No change");
23.57 +
23.58 + ListIterator<String> it = p.getNicknames().listIterator(1);
23.59 + assertEquals(it.next(), "Two");
23.60 + it.remove();
23.61 + assertEquals(it.next(), "Three");
23.62 + assertFalse(it.hasNext());
23.63 +
23.64 +
23.65 + assertEquals(one.changes, 1, "One change");
23.66 +
23.67 + it.set("3");
23.68 + assertEquals(p.getNicknames().get(1), "3");
23.69 +
23.70 + assertEquals(one.changes, 2, "Snd change");
23.71 + }
23.72
23.73 static final class One {
23.74 int changes;
24.1 --- a/ko-felix-test/src/main/java/org/netbeans/html/ko/felix/test/KnockoutFelixTCKImpl.java Tue Dec 09 07:23:22 2014 +0100
24.2 +++ b/ko-felix-test/src/main/java/org/netbeans/html/ko/felix/test/KnockoutFelixTCKImpl.java Tue Dec 09 08:33:22 2014 +0100
24.3 @@ -46,6 +46,7 @@
24.4 import java.io.IOException;
24.5 import java.io.InputStreamReader;
24.6 import java.lang.reflect.Constructor;
24.7 +import java.lang.reflect.InvocationTargetException;
24.8 import java.lang.reflect.Method;
24.9 import java.net.URI;
24.10 import java.net.URISyntaxException;
24.11 @@ -140,16 +141,9 @@
24.12 @Override
24.13 public BrwsrCtx createContext() {
24.14 try {
24.15 - Class<?> fxCls = loadOSGiClass(
24.16 - "org.netbeans.html.ko4j.FXContext",
24.17 - FrameworkUtil.getBundle(KnockoutFelixTCKImpl.class).getBundleContext()
24.18 - );
24.19 - final Constructor<?> cnstr = fxCls.getConstructor(Fn.Presenter.class);
24.20 - cnstr.setAccessible(true);
24.21 - Object fx = cnstr.newInstance(browserContext);
24.22 Contexts.Builder cb = Contexts.newBuilder().
24.23 - register(Technology.class, (Technology)fx, 10).
24.24 - register(Transfer.class, (Transfer)fx, 10).
24.25 + register(Technology.class, (Technology)osgiInstance("KOTech"), 10).
24.26 + register(Transfer.class, (Transfer)osgiInstance("KOTransfer"), 10).
24.27 register(Executor.class, (Executor)browserContext, 10);
24.28 // if (fx.areWebSocketsSupported()) {
24.29 // cb.register(WSTransfer.class, fx, 10);
24.30 @@ -160,6 +154,17 @@
24.31 }
24.32 }
24.33
24.34 + private Object osgiInstance(String simpleName) throws IllegalAccessException, SecurityException, IllegalArgumentException, Exception, NoSuchMethodException, InstantiationException, InvocationTargetException {
24.35 + Class<?> fxCls = loadOSGiClass(
24.36 + "org.netbeans.html.ko4j." + simpleName,
24.37 + FrameworkUtil.getBundle(KnockoutFelixTCKImpl.class).getBundleContext()
24.38 + );
24.39 + final Constructor<?> cnstr = fxCls.getDeclaredConstructor();
24.40 + cnstr.setAccessible(true);
24.41 + Object fx = cnstr.newInstance();
24.42 + return fx;
24.43 + }
24.44 +
24.45 @Override
24.46 public Object createJSON(Map<String, Object> values) {
24.47 JSONObject json = new JSONObject();
25.1 --- a/ko-osgi-test/src/main/java/org/netbeans/html/ko/osgi/test/KnockoutEquinoxTCKImpl.java Tue Dec 09 07:23:22 2014 +0100
25.2 +++ b/ko-osgi-test/src/main/java/org/netbeans/html/ko/osgi/test/KnockoutEquinoxTCKImpl.java Tue Dec 09 08:33:22 2014 +0100
25.3 @@ -46,6 +46,7 @@
25.4 import java.io.IOException;
25.5 import java.io.InputStreamReader;
25.6 import java.lang.reflect.Constructor;
25.7 +import java.lang.reflect.InvocationTargetException;
25.8 import java.lang.reflect.Method;
25.9 import java.net.URI;
25.10 import java.net.URISyntaxException;
25.11 @@ -135,16 +136,9 @@
25.12 @Override
25.13 public BrwsrCtx createContext() {
25.14 try {
25.15 - Class<?> fxCls = loadOSGiClass(
25.16 - "org.netbeans.html.ko4j.FXContext",
25.17 - FrameworkUtil.getBundle(KnockoutEquinoxTCKImpl.class).getBundleContext()
25.18 - );
25.19 - final Constructor<?> cnstr = fxCls.getConstructor(Fn.Presenter.class);
25.20 - cnstr.setAccessible(true);
25.21 - Object fx = cnstr.newInstance(browserContext);
25.22 Contexts.Builder cb = Contexts.newBuilder().
25.23 - register(Technology.class, (Technology)fx, 10).
25.24 - register(Transfer.class, (Transfer)fx, 10).
25.25 + register(Technology.class, (Technology)osgiInstance("KOTech"), 10).
25.26 + register(Transfer.class, (Transfer)osgiInstance("KOTransfer"), 10).
25.27 register(Executor.class, (Executor)browserContext, 10);
25.28 // if (fx.areWebSocketsSupported()) {
25.29 // cb.register(WSTransfer.class, fx, 10);
25.30 @@ -154,6 +148,16 @@
25.31 throw new IllegalStateException(ex);
25.32 }
25.33 }
25.34 + private Object osgiInstance(String simpleName) throws IllegalAccessException, SecurityException, IllegalArgumentException, Exception, NoSuchMethodException, InstantiationException, InvocationTargetException {
25.35 + Class<?> fxCls = loadOSGiClass(
25.36 + "org.netbeans.html.ko4j." + simpleName,
25.37 + FrameworkUtil.getBundle(KnockoutEquinoxTCKImpl.class).getBundleContext()
25.38 + );
25.39 + final Constructor<?> cnstr = fxCls.getDeclaredConstructor();
25.40 + cnstr.setAccessible(true);
25.41 + Object fx = cnstr.newInstance();
25.42 + return fx;
25.43 + }
25.44
25.45 @Override
25.46 public Object createJSON(Map<String, Object> values) {
26.1 --- a/ko-ws-tyrus/src/main/java/org/netbeans/html/wstyrus/TyrusContext.java Tue Dec 09 07:23:22 2014 +0100
26.2 +++ b/ko-ws-tyrus/src/main/java/org/netbeans/html/wstyrus/TyrusContext.java Tue Dec 09 08:33:22 2014 +0100
26.3 @@ -82,6 +82,7 @@
26.4 *
26.5 * @author Jaroslav Tulach
26.6 */
26.7 +@Contexts.Id("tyrus")
26.8 @ServiceProvider(service = Contexts.Provider.class)
26.9 public final class TyrusContext
26.10 implements Contexts.Provider, WSTransfer<Comm>, Transfer {
27.1 --- a/ko4j/pom.xml Tue Dec 09 07:23:22 2014 +0100
27.2 +++ b/ko4j/pom.xml Tue Dec 09 08:33:22 2014 +0100
27.3 @@ -15,6 +15,7 @@
27.4 <properties>
27.5 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
27.6 <bundleSymbolicName>org.netbeans.html.ko4j</bundleSymbolicName>
27.7 + <netbeans.compile.on.save>none</netbeans.compile.on.save>
27.8 </properties>
27.9 <build>
27.10 <plugins>
27.11 @@ -92,7 +93,6 @@
27.12 <groupId>javax.servlet</groupId>
27.13 <artifactId>javax.servlet-api</artifactId>
27.14 <scope>test</scope>
27.15 - <version>3.1.0</version>
27.16 </dependency>
27.17 </dependencies>
27.18 <description>Binds net.java.html.json APIs together with knockout.js</description>
28.1 --- a/ko4j/src/main/java/org/netbeans/html/ko4j/FXContext.java Tue Dec 09 07:23:22 2014 +0100
28.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
28.3 @@ -1,243 +0,0 @@
28.4 -/**
28.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
28.6 - *
28.7 - * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
28.8 - *
28.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
28.10 - * Other names may be trademarks of their respective owners.
28.11 - *
28.12 - * The contents of this file are subject to the terms of either the GNU
28.13 - * General Public License Version 2 only ("GPL") or the Common
28.14 - * Development and Distribution License("CDDL") (collectively, the
28.15 - * "License"). You may not use this file except in compliance with the
28.16 - * License. You can obtain a copy of the License at
28.17 - * http://www.netbeans.org/cddl-gplv2.html
28.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
28.19 - * specific language governing permissions and limitations under the
28.20 - * License. When distributing the software, include this License Header
28.21 - * Notice in each file and include the License file at
28.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
28.23 - * particular file as subject to the "Classpath" exception as provided
28.24 - * by Oracle in the GPL Version 2 section of the License file that
28.25 - * accompanied this code. If applicable, add the following below the
28.26 - * License Header, with the fields enclosed by brackets [] replaced by
28.27 - * your own identifying information:
28.28 - * "Portions Copyrighted [year] [name of copyright owner]"
28.29 - *
28.30 - * Contributor(s):
28.31 - *
28.32 - * The Original Software is NetBeans. The Initial Developer of the Original
28.33 - * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
28.34 - *
28.35 - * If you wish your version of this file to be governed by only the CDDL
28.36 - * or only the GPL Version 2, indicate your decision by adding
28.37 - * "[Contributor] elects to include this software in this distribution
28.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
28.39 - * single choice of license, a recipient has the option to distribute
28.40 - * your version of this file under either the CDDL, the GPL Version 2 or
28.41 - * to extend the choice of license to its licensees as provided above.
28.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
28.43 - * Version 2 license, then the option applies only if the new code is
28.44 - * made subject to such option by the copyright holder.
28.45 - */
28.46 -package org.netbeans.html.ko4j;
28.47 -
28.48 -import java.io.ByteArrayOutputStream;
28.49 -import java.io.IOException;
28.50 -import java.io.InputStream;
28.51 -import java.io.InputStreamReader;
28.52 -import java.io.Reader;
28.53 -import java.net.URL;
28.54 -import java.util.logging.Logger;
28.55 -import org.netbeans.html.boot.spi.Fn;
28.56 -import org.netbeans.html.json.spi.FunctionBinding;
28.57 -import org.netbeans.html.json.spi.JSONCall;
28.58 -import org.netbeans.html.json.spi.PropertyBinding;
28.59 -import org.netbeans.html.json.spi.Technology;
28.60 -import org.netbeans.html.json.spi.Transfer;
28.61 -import org.netbeans.html.json.spi.WSTransfer;
28.62 -
28.63 -/** This is an implementation package - just
28.64 - * include its JAR on classpath and use official {@link Context} API
28.65 - * to access the functionality.
28.66 - * <p>
28.67 - *
28.68 - * @author Jaroslav Tulach
28.69 - */
28.70 -final class FXContext
28.71 -implements Technology.BatchInit<Object>, Technology.ValueMutated<Object>,
28.72 -Transfer, WSTransfer<LoadWS> {
28.73 - static final Logger LOG = Logger.getLogger(FXContext.class.getName());
28.74 - private Object[] jsObjects;
28.75 - private int jsIndex;
28.76 -
28.77 - public FXContext(Fn.Presenter browserContext) {
28.78 - }
28.79 -
28.80 - @Override
28.81 - public Object wrapModel(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
28.82 - String[] propNames = new String[propArr.length];
28.83 - boolean[] propReadOnly = new boolean[propArr.length];
28.84 - Object[] propValues = new Object[propArr.length];
28.85 - for (int i = 0; i < propNames.length; i++) {
28.86 - propNames[i] = propArr[i].getPropertyName();
28.87 - propReadOnly[i] = propArr[i].isReadOnly();
28.88 - propValues[i] = propArr[i].getValue();
28.89 - }
28.90 - String[] funcNames = new String[funcArr.length];
28.91 - for (int i = 0; i < funcNames.length; i++) {
28.92 - funcNames[i] = funcArr[i].getFunctionName();
28.93 - }
28.94 - Object ret = getJSObject();
28.95 - Knockout.wrapModel(new Knockout(model, ret, propArr, funcArr),
28.96 - ret,
28.97 - propNames, propReadOnly, propValues,
28.98 - funcNames
28.99 - );
28.100 - return ret;
28.101 - }
28.102 -
28.103 - private Object getJSObject() {
28.104 - int len = 64;
28.105 - if (jsObjects != null && jsIndex < (len = jsObjects.length)) {
28.106 - Object ret = jsObjects[jsIndex];
28.107 - jsObjects[jsIndex] = null;
28.108 - jsIndex++;
28.109 - return ret;
28.110 - }
28.111 - jsObjects = Knockout.allocJS(len * 2);
28.112 - jsIndex = 1;
28.113 - Object ret = jsObjects[0];
28.114 - jsObjects[0] = null;
28.115 - return ret;
28.116 - }
28.117 -
28.118 - @Override
28.119 - public Object wrapModel(Object model) {
28.120 - throw new UnsupportedOperationException();
28.121 - }
28.122 -
28.123 - @Override
28.124 - public void bind(PropertyBinding b, Object model, Object data) {
28.125 - throw new UnsupportedOperationException();
28.126 - }
28.127 -
28.128 - @Override
28.129 - public void valueHasMutated(Object data, String propertyName) {
28.130 - Knockout.cleanUp();
28.131 - Knockout.valueHasMutated(data, propertyName, null, null);
28.132 - }
28.133 -
28.134 - @Override
28.135 - public void valueHasMutated(Object data, String propertyName, Object oldValue, Object newValue) {
28.136 - Knockout.cleanUp();
28.137 - Knockout.valueHasMutated(data, propertyName, oldValue, newValue);
28.138 - }
28.139 -
28.140 - @Override
28.141 - public void expose(FunctionBinding fb, Object model, Object d) {
28.142 - throw new UnsupportedOperationException();
28.143 - }
28.144 -
28.145 - @Override
28.146 - public void applyBindings(Object data) {
28.147 - Object ko = Knockout.applyBindings(data);
28.148 - if (ko instanceof Knockout) {
28.149 - ((Knockout)ko).hold();
28.150 - }
28.151 - }
28.152 -
28.153 - @Override
28.154 - public Object wrapArray(Object[] arr) {
28.155 - return arr;
28.156 - }
28.157 -
28.158 - @Override
28.159 - public void extract(Object obj, String[] props, Object[] values) {
28.160 - LoadJSON.extractJSON(obj, props, values);
28.161 - }
28.162 -
28.163 - @Override
28.164 - public void loadJSON(final JSONCall call) {
28.165 - if (call.isJSONP()) {
28.166 - String me = LoadJSON.createJSONP(call);
28.167 - LoadJSON.loadJSONP(call.composeURL(me), me);
28.168 - } else {
28.169 - String data = null;
28.170 - if (call.isDoOutput()) {
28.171 - try {
28.172 - ByteArrayOutputStream bos = new ByteArrayOutputStream();
28.173 - call.writeData(bos);
28.174 - data = new String(bos.toByteArray(), "UTF-8");
28.175 - } catch (IOException ex) {
28.176 - call.notifyError(ex);
28.177 - }
28.178 - }
28.179 - LoadJSON.loadJSON(call.composeURL(null), call, call.getMethod(), data);
28.180 - }
28.181 - }
28.182 -
28.183 - @Override
28.184 - public <M> M toModel(Class<M> modelClass, Object data) {
28.185 - return modelClass.cast(Knockout.toModel(data));
28.186 - }
28.187 -
28.188 - @Override
28.189 - public Object toJSON(InputStream is) throws IOException {
28.190 - StringBuilder sb = new StringBuilder();
28.191 - InputStreamReader r = new InputStreamReader(is);
28.192 - for (;;) {
28.193 - int ch = r.read();
28.194 - if (ch == -1) {
28.195 - break;
28.196 - }
28.197 - sb.append((char)ch);
28.198 - }
28.199 - return LoadJSON.parse(sb.toString());
28.200 - }
28.201 -
28.202 - @Override
28.203 - public void runSafe(final Runnable r) {
28.204 - LOG.warning("Technology.runSafe has been deprecated. Use BrwsrCtx.execute!");
28.205 - r.run();
28.206 - }
28.207 -
28.208 - @Override
28.209 - public LoadWS open(String url, JSONCall onReply) {
28.210 - return new LoadWS(onReply, url);
28.211 - }
28.212 -
28.213 - @Override
28.214 - public void send(LoadWS socket, JSONCall data) {
28.215 - socket.send(data);
28.216 - }
28.217 -
28.218 - @Override
28.219 - public void close(LoadWS socket) {
28.220 - socket.close();
28.221 - }
28.222 -
28.223 - boolean areWebSocketsSupported() {
28.224 - return Knockout.areWebSocketsSupported();
28.225 - }
28.226 -
28.227 - private static final class TrueFn extends Fn implements Fn.Presenter {
28.228 - @Override
28.229 - public Object invoke(Object thiz, Object... args) throws Exception {
28.230 - return true;
28.231 - }
28.232 -
28.233 - @Override
28.234 - public Fn defineFn(String code, String... names) {
28.235 - return this;
28.236 - }
28.237 -
28.238 - @Override
28.239 - public void displayPage(URL page, Runnable onPageLoad) {
28.240 - }
28.241 -
28.242 - @Override
28.243 - public void loadScript(Reader code) throws Exception {
28.244 - }
28.245 - } // end of TrueFn
28.246 -}
29.1 --- a/ko4j/src/main/java/org/netbeans/html/ko4j/KO4J.java Tue Dec 09 07:23:22 2014 +0100
29.2 +++ b/ko4j/src/main/java/org/netbeans/html/ko4j/KO4J.java Tue Dec 09 08:33:22 2014 +0100
29.3 @@ -42,7 +42,9 @@
29.4 */
29.5 package org.netbeans.html.ko4j;
29.6
29.7 +import java.util.logging.Logger;
29.8 import net.java.html.json.Model;
29.9 +import net.java.html.json.OnReceive;
29.10 import org.netbeans.html.boot.spi.Fn;
29.11 import org.netbeans.html.context.spi.Contexts;
29.12 import org.netbeans.html.context.spi.Contexts.Provider;
29.13 @@ -54,35 +56,49 @@
29.14 /** Support for <a href="http://knockoutjs.com">knockout.js</a>
29.15 * and its Java binding via {@link Model model classes}.
29.16 * Registers {@link Provider}, so {@link java.util.ServiceLoader} can find it.
29.17 + * The provider registers following technologies:
29.18 + * <ul>
29.19 + * <li><b>ko4j</b> - bindings for <a href="http://knockoutjs.com">knockout.js</a>
29.20 + * and the classes generated by the {@link Model} annotation.
29.21 + * </li>
29.22 + * <li><b>xhr</b> - <a href="http://www.w3.org/TR/XMLHttpRequest/">XMLHttpRequest</a>
29.23 + * based implementation for <em>REST</em> calls
29.24 + * (<b>GET</b>, <b>PUT</b>, <b>POST</b>, <b>DELETE</b> methods)
29.25 + * for {@link OnReceive} annotation.
29.26 + * </li>
29.27 + * <li><b>websocket</b> -
29.28 + * native browser <a href="http://www.w3.org/TR/websockets/">websockets</a>
29.29 + * based implementation for {@link OnReceive} annotation and its <b>WebSocket</b>
29.30 + * subprotocol.
29.31 + * </li>
29.32 + * </ul>
29.33 *
29.34 * @author Jaroslav Tulach
29.35 * @since 0.7
29.36 */
29.37 @ServiceProvider(service = Provider.class)
29.38 public final class KO4J implements Provider {
29.39 - private final Fn.Presenter presenter;
29.40 - private FXContext c;
29.41 + static final Logger LOG = Logger.getLogger(KOSockets.class.getName());
29.42 + private KOTech ko4j;
29.43 + private KOTransfer trans;
29.44 + private KOSockets socks;
29.45
29.46 public KO4J() {
29.47 this(null);
29.48 }
29.49 -
29.50 +
29.51 + @Deprecated
29.52 public KO4J(Fn.Presenter presenter) {
29.53 - this.presenter = presenter;
29.54 - }
29.55 -
29.56 - private FXContext getKO() {
29.57 - if (c == null) {
29.58 - c = new FXContext(presenter == null ? Fn.activePresenter() : presenter);
29.59 - }
29.60 - return c;
29.61 }
29.62
29.63 /** Return instance of the knockout.js for Java technology.
29.64 * @return non-null instance
29.65 */
29.66 public Technology knockout() {
29.67 - return getKO();
29.68 + if (ko4j == null) {
29.69 + ko4j = new KOTech();
29.70 + }
29.71 + return ko4j;
29.72 }
29.73
29.74 /** Browser based implementation of transfer interface. Uses
29.75 @@ -91,7 +107,10 @@
29.76 * @return non-null instance
29.77 */
29.78 public Transfer transfer() {
29.79 - return getKO();
29.80 + if (trans == null) {
29.81 + trans = new KOTransfer();
29.82 + }
29.83 + return trans;
29.84 }
29.85
29.86 /** Returns browser based implementation of websocket transfer.
29.87 @@ -102,7 +121,13 @@
29.88 * <code>WebSocket</code> object in the browser
29.89 */
29.90 public WSTransfer<?> websockets() {
29.91 - return getKO().areWebSocketsSupported() ? getKO() : null;
29.92 + if (!KOSockets.areWebSocketsSupported()) {
29.93 + return null;
29.94 + }
29.95 + if (socks == null) {
29.96 + socks = new KOSockets();
29.97 + }
29.98 + return socks;
29.99 }
29.100
29.101 /** Registers technologies at position 100:
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
30.2 +++ b/ko4j/src/main/java/org/netbeans/html/ko4j/KOSockets.java Tue Dec 09 08:33:22 2014 +0100
30.3 @@ -0,0 +1,81 @@
30.4 +/**
30.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
30.6 + *
30.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
30.8 + *
30.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
30.10 + * Other names may be trademarks of their respective owners.
30.11 + *
30.12 + * The contents of this file are subject to the terms of either the GNU
30.13 + * General Public License Version 2 only ("GPL") or the Common
30.14 + * Development and Distribution License("CDDL") (collectively, the
30.15 + * "License"). You may not use this file except in compliance with the
30.16 + * License. You can obtain a copy of the License at
30.17 + * http://www.netbeans.org/cddl-gplv2.html
30.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
30.19 + * specific language governing permissions and limitations under the
30.20 + * License. When distributing the software, include this License Header
30.21 + * Notice in each file and include the License file at
30.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
30.23 + * particular file as subject to the "Classpath" exception as provided
30.24 + * by Oracle in the GPL Version 2 section of the License file that
30.25 + * accompanied this code. If applicable, add the following below the
30.26 + * License Header, with the fields enclosed by brackets [] replaced by
30.27 + * your own identifying information:
30.28 + * "Portions Copyrighted [year] [name of copyright owner]"
30.29 + *
30.30 + * Contributor(s):
30.31 + *
30.32 + * The Original Software is NetBeans. The Initial Developer of the Original
30.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
30.34 + *
30.35 + * If you wish your version of this file to be governed by only the CDDL
30.36 + * or only the GPL Version 2, indicate your decision by adding
30.37 + * "[Contributor] elects to include this software in this distribution
30.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
30.39 + * single choice of license, a recipient has the option to distribute
30.40 + * your version of this file under either the CDDL, the GPL Version 2 or
30.41 + * to extend the choice of license to its licensees as provided above.
30.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
30.43 + * Version 2 license, then the option applies only if the new code is
30.44 + * made subject to such option by the copyright holder.
30.45 + */
30.46 +package org.netbeans.html.ko4j;
30.47 +
30.48 +import net.java.html.js.JavaScriptBody;
30.49 +import org.netbeans.html.context.spi.Contexts;
30.50 +import org.netbeans.html.json.spi.JSONCall;
30.51 +import org.netbeans.html.json.spi.WSTransfer;
30.52 +
30.53 +/** This is an implementation package - just
30.54 + * include its JAR on classpath and use official {@link Context} API
30.55 + * to access the functionality.
30.56 + *
30.57 + * @author Jaroslav Tulach
30.58 + */
30.59 +@Contexts.Id("websocket")
30.60 +final class KOSockets
30.61 +implements WSTransfer<LoadWS> {
30.62 + KOSockets() {
30.63 + }
30.64 +
30.65 + @Override
30.66 + public LoadWS open(String url, JSONCall onReply) {
30.67 + return new LoadWS(onReply, url);
30.68 + }
30.69 +
30.70 + @Override
30.71 + public void send(LoadWS socket, JSONCall data) {
30.72 + socket.send(data);
30.73 + }
30.74 +
30.75 + @Override
30.76 + public void close(LoadWS socket) {
30.77 + socket.close();
30.78 + }
30.79 +
30.80 + @JavaScriptBody(args = {}, body = "if (window['WebSocket']) return true; else return false;")
30.81 + static final boolean areWebSocketsSupported() {
30.82 + return false;
30.83 + }
30.84 +}
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
31.2 +++ b/ko4j/src/main/java/org/netbeans/html/ko4j/KOTech.java Tue Dec 09 08:33:22 2014 +0100
31.3 @@ -0,0 +1,155 @@
31.4 +/**
31.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
31.6 + *
31.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
31.8 + *
31.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
31.10 + * Other names may be trademarks of their respective owners.
31.11 + *
31.12 + * The contents of this file are subject to the terms of either the GNU
31.13 + * General Public License Version 2 only ("GPL") or the Common
31.14 + * Development and Distribution License("CDDL") (collectively, the
31.15 + * "License"). You may not use this file except in compliance with the
31.16 + * License. You can obtain a copy of the License at
31.17 + * http://www.netbeans.org/cddl-gplv2.html
31.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
31.19 + * specific language governing permissions and limitations under the
31.20 + * License. When distributing the software, include this License Header
31.21 + * Notice in each file and include the License file at
31.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
31.23 + * particular file as subject to the "Classpath" exception as provided
31.24 + * by Oracle in the GPL Version 2 section of the License file that
31.25 + * accompanied this code. If applicable, add the following below the
31.26 + * License Header, with the fields enclosed by brackets [] replaced by
31.27 + * your own identifying information:
31.28 + * "Portions Copyrighted [year] [name of copyright owner]"
31.29 + *
31.30 + * Contributor(s):
31.31 + *
31.32 + * The Original Software is NetBeans. The Initial Developer of the Original
31.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
31.34 + *
31.35 + * If you wish your version of this file to be governed by only the CDDL
31.36 + * or only the GPL Version 2, indicate your decision by adding
31.37 + * "[Contributor] elects to include this software in this distribution
31.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
31.39 + * single choice of license, a recipient has the option to distribute
31.40 + * your version of this file under either the CDDL, the GPL Version 2 or
31.41 + * to extend the choice of license to its licensees as provided above.
31.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
31.43 + * Version 2 license, then the option applies only if the new code is
31.44 + * made subject to such option by the copyright holder.
31.45 + */
31.46 +package org.netbeans.html.ko4j;
31.47 +
31.48 +import org.netbeans.html.context.spi.Contexts;
31.49 +import org.netbeans.html.json.spi.FunctionBinding;
31.50 +import org.netbeans.html.json.spi.PropertyBinding;
31.51 +import org.netbeans.html.json.spi.Technology;
31.52 +import static org.netbeans.html.ko4j.KO4J.LOG;
31.53 +
31.54 +/** This is an implementation package - just
31.55 + * include its JAR on classpath and use official {@link Context} API
31.56 + * to access the functionality.
31.57 + * <p>
31.58 + *
31.59 + * @author Jaroslav Tulach
31.60 + */
31.61 +@Contexts.Id("ko4j")
31.62 +final class KOTech
31.63 +implements Technology.BatchInit<Object>, Technology.ValueMutated<Object> {
31.64 + private Object[] jsObjects;
31.65 + private int jsIndex;
31.66 +
31.67 + public KOTech() {
31.68 + }
31.69 +
31.70 + @Override
31.71 + public Object wrapModel(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
31.72 + String[] propNames = new String[propArr.length];
31.73 + boolean[] propReadOnly = new boolean[propArr.length];
31.74 + Object[] propValues = new Object[propArr.length];
31.75 + for (int i = 0; i < propNames.length; i++) {
31.76 + propNames[i] = propArr[i].getPropertyName();
31.77 + propReadOnly[i] = propArr[i].isReadOnly();
31.78 + propValues[i] = propArr[i].getValue();
31.79 + }
31.80 + String[] funcNames = new String[funcArr.length];
31.81 + for (int i = 0; i < funcNames.length; i++) {
31.82 + funcNames[i] = funcArr[i].getFunctionName();
31.83 + }
31.84 + Object ret = getJSObject();
31.85 + Knockout.wrapModel(new Knockout(model, ret, propArr, funcArr),
31.86 + ret,
31.87 + propNames, propReadOnly, propValues,
31.88 + funcNames
31.89 + );
31.90 + return ret;
31.91 + }
31.92 +
31.93 + private Object getJSObject() {
31.94 + int len = 64;
31.95 + if (jsObjects != null && jsIndex < (len = jsObjects.length)) {
31.96 + Object ret = jsObjects[jsIndex];
31.97 + jsObjects[jsIndex] = null;
31.98 + jsIndex++;
31.99 + return ret;
31.100 + }
31.101 + jsObjects = Knockout.allocJS(len * 2);
31.102 + jsIndex = 1;
31.103 + Object ret = jsObjects[0];
31.104 + jsObjects[0] = null;
31.105 + return ret;
31.106 + }
31.107 +
31.108 + @Override
31.109 + public Object wrapModel(Object model) {
31.110 + throw new UnsupportedOperationException();
31.111 + }
31.112 +
31.113 + @Override
31.114 + public void bind(PropertyBinding b, Object model, Object data) {
31.115 + throw new UnsupportedOperationException();
31.116 + }
31.117 +
31.118 + @Override
31.119 + public void valueHasMutated(Object data, String propertyName) {
31.120 + Knockout.cleanUp();
31.121 + Knockout.valueHasMutated(data, propertyName, null, null);
31.122 + }
31.123 +
31.124 + @Override
31.125 + public void valueHasMutated(Object data, String propertyName, Object oldValue, Object newValue) {
31.126 + Knockout.cleanUp();
31.127 + Knockout.valueHasMutated(data, propertyName, oldValue, newValue);
31.128 + }
31.129 +
31.130 + @Override
31.131 + public void expose(FunctionBinding fb, Object model, Object d) {
31.132 + throw new UnsupportedOperationException();
31.133 + }
31.134 +
31.135 + @Override
31.136 + public void applyBindings(Object data) {
31.137 + Object ko = Knockout.applyBindings(data);
31.138 + if (ko instanceof Knockout) {
31.139 + ((Knockout)ko).hold();
31.140 + }
31.141 + }
31.142 +
31.143 + @Override
31.144 + public Object wrapArray(Object[] arr) {
31.145 + return arr;
31.146 + }
31.147 +
31.148 + @Override
31.149 + public void runSafe(final Runnable r) {
31.150 + LOG.warning("Technology.runSafe has been deprecated. Use BrwsrCtx.execute!");
31.151 + r.run();
31.152 + }
31.153 +
31.154 + @Override
31.155 + public <M> M toModel(Class<M> modelClass, Object data) {
31.156 + return modelClass.cast(Knockout.toModel(data));
31.157 + }
31.158 +}
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
32.2 +++ b/ko4j/src/main/java/org/netbeans/html/ko4j/KOTransfer.java Tue Dec 09 08:33:22 2014 +0100
32.3 @@ -0,0 +1,104 @@
32.4 +/**
32.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
32.6 + *
32.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
32.8 + *
32.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
32.10 + * Other names may be trademarks of their respective owners.
32.11 + *
32.12 + * The contents of this file are subject to the terms of either the GNU
32.13 + * General Public License Version 2 only ("GPL") or the Common
32.14 + * Development and Distribution License("CDDL") (collectively, the
32.15 + * "License"). You may not use this file except in compliance with the
32.16 + * License. You can obtain a copy of the License at
32.17 + * http://www.netbeans.org/cddl-gplv2.html
32.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
32.19 + * specific language governing permissions and limitations under the
32.20 + * License. When distributing the software, include this License Header
32.21 + * Notice in each file and include the License file at
32.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
32.23 + * particular file as subject to the "Classpath" exception as provided
32.24 + * by Oracle in the GPL Version 2 section of the License file that
32.25 + * accompanied this code. If applicable, add the following below the
32.26 + * License Header, with the fields enclosed by brackets [] replaced by
32.27 + * your own identifying information:
32.28 + * "Portions Copyrighted [year] [name of copyright owner]"
32.29 + *
32.30 + * Contributor(s):
32.31 + *
32.32 + * The Original Software is NetBeans. The Initial Developer of the Original
32.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
32.34 + *
32.35 + * If you wish your version of this file to be governed by only the CDDL
32.36 + * or only the GPL Version 2, indicate your decision by adding
32.37 + * "[Contributor] elects to include this software in this distribution
32.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
32.39 + * single choice of license, a recipient has the option to distribute
32.40 + * your version of this file under either the CDDL, the GPL Version 2 or
32.41 + * to extend the choice of license to its licensees as provided above.
32.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
32.43 + * Version 2 license, then the option applies only if the new code is
32.44 + * made subject to such option by the copyright holder.
32.45 + */
32.46 +package org.netbeans.html.ko4j;
32.47 +
32.48 +import java.io.ByteArrayOutputStream;
32.49 +import java.io.IOException;
32.50 +import java.io.InputStream;
32.51 +import java.io.InputStreamReader;
32.52 +import org.netbeans.html.context.spi.Contexts;
32.53 +import org.netbeans.html.json.spi.JSONCall;
32.54 +import org.netbeans.html.json.spi.Transfer;
32.55 +
32.56 +/** This is an implementation package - just
32.57 + * include its JAR on classpath and use official {@link Context} API
32.58 + * to access the functionality.
32.59 + * <p>
32.60 + *
32.61 + * @author Jaroslav Tulach
32.62 + */
32.63 +@Contexts.Id("xhr")
32.64 +final class KOTransfer
32.65 +implements Transfer {
32.66 + KOTransfer() {
32.67 + }
32.68 +
32.69 + @Override
32.70 + public void extract(Object obj, String[] props, Object[] values) {
32.71 + LoadJSON.extractJSON(obj, props, values);
32.72 + }
32.73 +
32.74 + @Override
32.75 + public void loadJSON(final JSONCall call) {
32.76 + if (call.isJSONP()) {
32.77 + String me = LoadJSON.createJSONP(call);
32.78 + LoadJSON.loadJSONP(call.composeURL(me), me);
32.79 + } else {
32.80 + String data = null;
32.81 + if (call.isDoOutput()) {
32.82 + try {
32.83 + ByteArrayOutputStream bos = new ByteArrayOutputStream();
32.84 + call.writeData(bos);
32.85 + data = new String(bos.toByteArray(), "UTF-8");
32.86 + } catch (IOException ex) {
32.87 + call.notifyError(ex);
32.88 + }
32.89 + }
32.90 + LoadJSON.loadJSON(call.composeURL(null), call, call.getMethod(), data);
32.91 + }
32.92 + }
32.93 +
32.94 + @Override
32.95 + public Object toJSON(InputStream is) throws IOException {
32.96 + StringBuilder sb = new StringBuilder();
32.97 + InputStreamReader r = new InputStreamReader(is);
32.98 + for (;;) {
32.99 + int ch = r.read();
32.100 + if (ch == -1) {
32.101 + break;
32.102 + }
32.103 + sb.append((char)ch);
32.104 + }
32.105 + return LoadJSON.parse(sb.toString());
32.106 + }
32.107 +}
33.1 --- a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java Tue Dec 09 07:23:22 2014 +0100
33.2 +++ b/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java Tue Dec 09 08:33:22 2014 +0100
33.3 @@ -229,9 +229,4 @@
33.4 return o;
33.5 }
33.6 }
33.7 -
33.8 - @JavaScriptBody(args = {}, body = "if (window['WebSocket']) return true; else return false;")
33.9 - static final boolean areWebSocketsSupported() {
33.10 - return false;
33.11 - }
33.12 }
34.1 --- a/ko4j/src/test/java/org/netbeans/html/ko4j/KnockoutFXTest.java Tue Dec 09 07:23:22 2014 +0100
34.2 +++ b/ko4j/src/test/java/org/netbeans/html/ko4j/KnockoutFXTest.java Tue Dec 09 08:33:22 2014 +0100
34.3 @@ -153,12 +153,12 @@
34.4
34.5 @Override
34.6 public BrwsrCtx createContext() {
34.7 - FXContext fx = new FXContext(browserContext);
34.8 + KO4J ko4j = new KO4J();
34.9 Contexts.Builder cb = Contexts.newBuilder().
34.10 - register(Technology.class, fx, 10).
34.11 - register(Transfer.class, fx, 10);
34.12 - if (fx.areWebSocketsSupported()) {
34.13 - cb.register(WSTransfer.class, fx, 10);
34.14 + register(Technology.class, ko4j.knockout(), 10).
34.15 + register(Transfer.class, ko4j.transfer(), 10);
34.16 + if (ko4j.websockets() != null) {
34.17 + cb.register(WSTransfer.class, ko4j.websockets(), 10);
34.18 }
34.19 cb.register(Executor.class, (Executor)browserContext, 10);
34.20 cb.register(Fn.Presenter.class, browserContext, 10);
35.1 --- a/pom.xml Tue Dec 09 07:23:22 2014 +0100
35.2 +++ b/pom.xml Tue Dec 09 08:33:22 2014 +0100
35.3 @@ -35,6 +35,7 @@
35.4 <module>ko-osgi-test</module>
35.5 <module>equinox-agentclass-hook</module>
35.6 <module>boot-script</module>
35.7 + <module>boot-agent-test</module>
35.8 </modules>
35.9 <licenses>
35.10 <license>
35.11 @@ -246,7 +247,7 @@
35.12 <dependency>
35.13 <groupId>org.ow2.asm</groupId>
35.14 <artifactId>asm</artifactId>
35.15 - <version>4.1</version>
35.16 + <version>5.0</version>
35.17 </dependency>
35.18 <dependency>
35.19 <groupId>org.netbeans.api</groupId>
36.1 --- a/src/main/javadoc/overview.html Tue Dec 09 07:23:22 2014 +0100
36.2 +++ b/src/main/javadoc/overview.html Tue Dec 09 08:33:22 2014 +0100
36.3 @@ -78,6 +78,22 @@
36.4 <h3>What's New in Version 1.1?</h3>
36.5
36.6 <p>
36.7 + The content of a {@link net.java.html.BrwsrCtx context}
36.8 + can be selected by registering implementations under specific
36.9 + {@link org.netbeans.html.context.spi.Contexts.Id technology identifiers}
36.10 + and requesting them during
36.11 + {@link org.netbeans.html.context.spi.Contexts#newBuilder(java.lang.Object...) construction}
36.12 + of the context. <code>org.netbeans.html:ko4j</code> module's implementation
36.13 + offers <b>ko4j</b>, <b>xhr</b> and <b>websocket</b> identifiers
36.14 + for its registered services
36.15 + (e.g. {@link org.netbeans.html.json.spi.Technology},
36.16 + {@link org.netbeans.html.json.spi.Transfer} and
36.17 + {@link org.netbeans.html.json.spi.WSTransfer}).
36.18 + <code>org.netbeans.html:ko-ws-tyrus</code>
36.19 + module registers its
36.20 + {@link org.netbeans.html.json.spi.Transfer Java based JSON} and
36.21 + {@link org.netbeans.html.json.spi.WSTransfer WebSocket} implementations
36.22 + under the name <b>tyrus</b>.
36.23 Memory model when using Knockout bindings has been improved
36.24 (required additions of two new methods:
36.25 {@link org.netbeans.html.json.spi.PropertyBinding#weak()} and
36.26 @@ -107,6 +123,28 @@
36.27 prevent endless debugging when one forgets to do so.
36.28 </p>
36.29
36.30 + <p>
36.31 + What's new in older versions? Click the
36.32 + <a href="#" onclick="return showHistoric(true)">link</a>
36.33 + to view even more
36.34 + <a href="#" onclick="return showHistoric(true)">historic changes</a> below:
36.35 + </p>
36.36 +
36.37 + <a name="historic.changes"></a>
36.38 + <div id="historic.changes">
36.39 + <script>
36.40 + function showHistoric(show) {
36.41 + var e = document.getElementById("historic.changes");
36.42 + if (show) {
36.43 + e.style.display="block";
36.44 + } else {
36.45 + e.style.display="none";
36.46 + }
36.47 + return false;
36.48 + }
36.49 + showHistoric(false);
36.50 + </script>
36.51 +
36.52 <h3>What's New in Version 0.9?</h3>
36.53
36.54 <p>
36.55 @@ -173,7 +211,7 @@
36.56 </p>
36.57
36.58
36.59 - <h3>What's New in Older Versions?</h3>
36.60 + <h3>What's New in 0.7.x Versions?</h3>
36.61
36.62 <p>
36.63 {@link net.java.html.js.JavaScriptBody} annotation has new attribute
36.64 @@ -190,6 +228,7 @@
36.65 See example
36.66 {@link net.java.html.BrwsrCtx#execute(java.lang.Runnable) using Java timer}.
36.67 </p>
36.68 + </div>
36.69
36.70 <h3>Interesting Entry Points</h3>
36.71