Merging with most recent changes on the default branch. Including switch to org.netbeans.html namespace. preprocess
authorJaroslav Tulach <jaroslav.tulach@netbeans.org>
Tue, 07 Jan 2014 08:21:57 +0100
branchpreprocess
changeset 42166d823ed2f87
parent 368 0fba0a44fe6e
parent 420 70de86018481
child 425 6729b08befde
Merging with most recent changes on the default branch. Including switch to org.netbeans.html namespace.
boot-fx/pom.xml
boot-fx/src/main/java/org/apidesign/html/boot/fx/AbstractFXPresenter.java
boot-fx/src/main/java/org/apidesign/html/boot/fx/Dbgr.java
boot-fx/src/main/java/org/apidesign/html/boot/fx/FXBrwsr.java
boot-fx/src/main/java/org/apidesign/html/boot/fx/FXInspect.java
boot-fx/src/main/java/org/apidesign/html/boot/fx/FXPresenter.java
boot-fx/src/test/java/org/apidesign/html/boot/fx/BootstrapTest.java
boot-fx/src/test/java/org/apidesign/html/boot/fx/FxJavaScriptTst.java
boot-fx/src/test/java/org/apidesign/html/boot/fx/KOFx.java
boot-fx/src/test/java/org/netbeans/html/boot/fx/BootstrapTest.java
boot-fx/src/test/java/org/netbeans/html/boot/fx/FxJavaScriptTst.java
boot-fx/src/test/resources/org/apidesign/html/boot/fx/empty.html
boot/pom.xml
boot/src/main/java/org/apidesign/html/boot/impl/FindResources.java
boot/src/main/java/org/apidesign/html/boot/impl/FnContext.java
boot/src/main/java/org/apidesign/html/boot/impl/FnUtils.java
boot/src/main/java/org/apidesign/html/boot/impl/JavaScriptProcesor.java
boot/src/main/java/org/apidesign/html/boot/impl/JsAgent.java
boot/src/main/java/org/apidesign/html/boot/impl/JsCallback.java
boot/src/main/java/org/apidesign/html/boot/impl/JsClassLoader.java
boot/src/main/java/org/apidesign/html/boot/impl/Test.java
boot/src/main/java/org/apidesign/html/boot/spi/Fn.java
boot/src/main/java/org/netbeans/html/boot/impl/FnContext.java
boot/src/main/java/org/netbeans/html/boot/impl/FnUtils.java
boot/src/main/java/org/netbeans/html/boot/impl/JsAgent.java
boot/src/main/java/org/netbeans/html/boot/impl/JsClassLoader.java
boot/src/test/java/org/apidesign/html/boot/impl/Arithm.java
boot/src/test/java/org/apidesign/html/boot/impl/Compile.java
boot/src/test/java/org/apidesign/html/boot/impl/FnTest.java
boot/src/test/java/org/apidesign/html/boot/impl/JavaScriptProcesorTest.java
boot/src/test/java/org/apidesign/html/boot/impl/JsClassLoaderBase.java
boot/src/test/java/org/apidesign/html/boot/impl/JsClassLoaderTest.java
boot/src/test/java/org/apidesign/html/boot/impl/JsMethods.java
boot/src/test/resources/org/apidesign/html/boot/impl/jsmethods.js
context/src/main/java/org/apidesign/html/context/impl/CtxAccssr.java
context/src/main/java/org/apidesign/html/context/impl/CtxImpl.java
geo/src/main/java/org/apidesign/html/geo/impl/GeoProcessor.java
geo/src/main/java/org/apidesign/html/geo/impl/JsG.java
geo/src/test/java/org/apidesign/html/geo/impl/Compile.java
geo/src/test/java/org/apidesign/html/geo/impl/GeoProcessorTest.java
html4j-maven-plugin/src/main/java/org/apidesign/html/mojo/ProcessJsAnnotationsMojo.java
html4j-maven-plugin/src/test/java/org/apidesign/html/mojo/GenerateBodyTest.java
json-tck/pom.xml
json-tck/src/main/java/net/java/html/js/tests/Bodies.java
json-tck/src/main/java/net/java/html/js/tests/Factorial.java
json-tck/src/main/java/net/java/html/js/tests/JavaScriptBodyTest.java
json-tck/src/main/java/net/java/html/js/tests/Sum.java
json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java
json-tck/src/main/java/org/apidesign/html/json/tck/JavaScriptTCK.java
json-tck/src/main/java/org/apidesign/html/json/tck/KnockoutTCK.java
json/src/main/java/org/apidesign/html/json/impl/Bindings.java
json/src/main/java/org/apidesign/html/json/impl/Callback.java
json/src/main/java/org/apidesign/html/json/impl/FromJSON.java
json/src/main/java/org/apidesign/html/json/impl/JSON.java
json/src/main/java/org/apidesign/html/json/impl/JSONList.java
json/src/main/java/org/apidesign/html/json/impl/ModelProcessor.java
json/src/main/java/org/apidesign/html/json/impl/PropertyBindingAccessor.java
json/src/main/java/org/apidesign/html/json/impl/RcvrJSON.java
json/src/main/java/org/apidesign/html/json/impl/SetAndGet.java
json/src/main/java/org/apidesign/html/json/impl/WrapperObject.java
json/src/main/resources/org/apidesign/html/json/impl/Bundle.properties
json/src/main/resources/org/apidesign/html/json/spi/package.html
json/src/test/java/org/apidesign/html/json/impl/ConstructorTest.java
json/src/test/java/org/apidesign/html/json/impl/EmployeeImpl.java
json/src/test/java/org/apidesign/html/json/impl/EmployerTest.java
json/src/test/java/org/apidesign/html/json/impl/JSONListTest.java
json/src/test/java/org/apidesign/html/json/impl/JSONTest.java
json/src/test/java/org/apidesign/html/json/impl/NoPropertiesTest.java
ko-archetype-test/src/test/java/org/apidesign/html/archetype/test/ArchetypeVersionTest.java
ko-archetype-test/src/test/java/org/apidesign/html/archetype/test/VerifyArchetypeTest.java
ko-archetype/src/main/java/org/apidesign/html/archetype/package-info.java
ko-fx/src/main/java/org/apidesign/html/kofx/Console.java
ko-fx/src/main/java/org/apidesign/html/kofx/FXContext.java
ko-fx/src/main/java/org/apidesign/html/kofx/Knockout.java
ko-fx/src/main/java/org/apidesign/html/kofx/LoadJSON.java
ko-fx/src/main/java/org/apidesign/html/kofx/LoadWS.java
ko-fx/src/main/resources/org/apidesign/html/kofx/knockout-2.2.1.js
ko-fx/src/test/java/org/apidesign/html/kofx/DynamicHTTP.java
ko-fx/src/test/java/org/apidesign/html/kofx/KOFx.java
ko-fx/src/test/java/org/apidesign/html/kofx/KnockoutFXTest.java
ko-fx/src/test/java/org/apidesign/html/kofx/LessCallbacksCheck.java
ko-fx/src/test/java/org/netbeans/html/kofx/KnockoutFXTest.java
ko-fx/src/test/resources/org/apidesign/html/kofx/test.html
ko-ws-tyrus/src/main/java/org/apidesign/html/wstyrus/TyrusContext.java
ko-ws-tyrus/src/test/java/org/apidesign/html/wstyrus/TyrusDynamicHTTP.java
ko-ws-tyrus/src/test/java/org/apidesign/html/wstyrus/TyrusFX.java
ko-ws-tyrus/src/test/java/org/apidesign/html/wstyrus/TyrusKnockoutTest.java
ko-ws-tyrus/src/test/java/org/netbeans/html/wstyrus/TyrusKnockoutTest.java
ko-ws-tyrus/src/test/resources/org/apidesign/html/wstyrus/test.html
pom.xml
sound/src/main/java/org/apidesign/html/sound/impl/BrowserAudioEnv.java
     1.1 --- a/.hgtags	Thu Dec 19 17:11:01 2013 +0100
     1.2 +++ b/.hgtags	Tue Jan 07 08:21:57 2014 +0100
     1.3 @@ -6,3 +6,4 @@
     1.4  24612fed24b589c313c416a4e86df9cc4a2ecde5 release-0.4
     1.5  6656cca0a73a0f0c3d0a349f471a6c5bab6035a9 release-0.5
     1.6  3e5e3c96f9f13bc1487c46e050a6d545c427d945 release-0.6
     1.7 +53634fd10e30d0fcfd8d05a2bdf2df36c50ee237 netbeans_base
     2.1 --- a/COPYING	Thu Dec 19 17:11:01 2013 +0100
     2.2 +++ b/COPYING	Tue Jan 07 08:21:57 2014 +0100
     2.3 @@ -1,18 +1,40 @@
     2.4 -HTML via Java(tm) Language Bindings
     2.5 -Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     2.6 +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     2.7  
     2.8 -This program is free software: you can redistribute it and/or modify
     2.9 -it under the terms of the GNU General Public License as published by
    2.10 -the Free Software Foundation, version 2 of the License.
    2.11 +Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    2.12  
    2.13 -This program is distributed in the hope that it will be useful,
    2.14 -but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.15 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.16 -GNU General Public License for more details. apidesign.org 
    2.17 -designates this particular file as subject to the 
    2.18 -"Classpath" exception as provided by apidesign.org 
    2.19 -in the License file that accompanied this code.
    2.20 +Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    2.21 +Other names may be trademarks of their respective owners.
    2.22  
    2.23 -You should have received a copy of the GNU General Public License
    2.24 -along with this program. Look for COPYING file in the top folder.
    2.25 -If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    2.26 +The contents of this file are subject to the terms of either the GNU
    2.27 +General Public License Version 2 only ("GPL") or the Common
    2.28 +Development and Distribution License("CDDL") (collectively, the
    2.29 +"License"). You may not use this file except in compliance with the
    2.30 +License. You can obtain a copy of the License at
    2.31 +http://www.netbeans.org/cddl-gplv2.html
    2.32 +or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    2.33 +specific language governing permissions and limitations under the
    2.34 +License.  When distributing the software, include this License Header
    2.35 +Notice in each file and include the License file at
    2.36 +nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    2.37 +particular file as subject to the "Classpath" exception as provided
    2.38 +by Oracle in the GPL Version 2 section of the License file that
    2.39 +accompanied this code. If applicable, add the following below the
    2.40 +License Header, with the fields enclosed by brackets [] replaced by
    2.41 +your own identifying information:
    2.42 +"Portions Copyrighted [year] [name of copyright owner]"
    2.43 +
    2.44 +Contributor(s):
    2.45 +
    2.46 +The Original Software is NetBeans. The Initial Developer of the Original
    2.47 +Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
    2.48 +
    2.49 +If you wish your version of this file to be governed by only the CDDL
    2.50 +or only the GPL Version 2, indicate your decision by adding
    2.51 +"[Contributor] elects to include this software in this distribution
    2.52 +under the [CDDL or GPL Version 2] license." If you do not indicate a
    2.53 +single choice of license, a recipient has the option to distribute
    2.54 +your version of this file under either the CDDL, the GPL Version 2 or
    2.55 +to extend the choice of license to its licensees as provided above.
    2.56 +However, if you add GPL Version 2 code and therefore, elected the GPL
    2.57 +Version 2 license, then the option applies only if the new code is
    2.58 +made subject to such option by the copyright holder.
     3.1 --- a/boot-fx/pom.xml	Thu Dec 19 17:11:01 2013 +0100
     3.2 +++ b/boot-fx/pom.xml	Tue Jan 07 08:21:57 2014 +0100
     3.3 @@ -2,12 +2,12 @@
     3.4  <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">
     3.5    <modelVersion>4.0.0</modelVersion>
     3.6    <parent>
     3.7 -    <groupId>org.apidesign</groupId>
     3.8 -    <artifactId>html</artifactId>
     3.9 +    <groupId>org.netbeans.html</groupId>
    3.10 +    <artifactId>pom</artifactId>
    3.11      <version>0.7-SNAPSHOT</version>
    3.12    </parent>
    3.13 -  <groupId>org.apidesign.html</groupId>
    3.14 -  <artifactId>boot-fx</artifactId>
    3.15 +  <groupId>org.netbeans.html</groupId>
    3.16 +  <artifactId>net.java.html.boot.fx</artifactId>
    3.17    <version>0.7-SNAPSHOT</version>
    3.18    <name>FX WebView Bootstrap</name>
    3.19    <packaging>bundle</packaging>
    3.20 @@ -54,7 +54,7 @@
    3.21        <scope>provided</scope>
    3.22      </dependency>
    3.23      <dependency>
    3.24 -      <groupId>org.apidesign.html</groupId>
    3.25 +      <groupId>org.netbeans.html</groupId>
    3.26        <artifactId>net.java.html.boot</artifactId>
    3.27        <version>${project.version}</version>
    3.28        <type>jar</type>
     4.1 --- a/boot-fx/src/main/java/net/java/html/boot/fx/FXBrowsers.java	Thu Dec 19 17:11:01 2013 +0100
     4.2 +++ b/boot-fx/src/main/java/net/java/html/boot/fx/FXBrowsers.java	Tue Jan 07 08:21:57 2014 +0100
     4.3 @@ -1,22 +1,44 @@
     4.4  /**
     4.5 - * HTML via Java(tm) Language Bindings
     4.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     4.8   *
     4.9 - * This program is free software: you can redistribute it and/or modify
    4.10 - * it under the terms of the GNU General Public License as published by
    4.11 - * the Free Software Foundation, version 2 of the License.
    4.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    4.13   *
    4.14 - * This program is distributed in the hope that it will be useful,
    4.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.17 - * GNU General Public License for more details. apidesign.org
    4.18 - * designates this particular file as subject to the
    4.19 - * "Classpath" exception as provided by apidesign.org
    4.20 - * in the License file that accompanied this code.
    4.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    4.22 + * Other names may be trademarks of their respective owners.
    4.23   *
    4.24 - * You should have received a copy of the GNU General Public License
    4.25 - * along with this program. Look for COPYING file in the top folder.
    4.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    4.27 + * The contents of this file are subject to the terms of either the GNU
    4.28 + * General Public License Version 2 only ("GPL") or the Common
    4.29 + * Development and Distribution License("CDDL") (collectively, the
    4.30 + * "License"). You may not use this file except in compliance with the
    4.31 + * License. You can obtain a copy of the License at
    4.32 + * http://www.netbeans.org/cddl-gplv2.html
    4.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    4.34 + * specific language governing permissions and limitations under the
    4.35 + * License.  When distributing the software, include this License Header
    4.36 + * Notice in each file and include the License file at
    4.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    4.38 + * particular file as subject to the "Classpath" exception as provided
    4.39 + * by Oracle in the GPL Version 2 section of the License file that
    4.40 + * accompanied this code. If applicable, add the following below the
    4.41 + * License Header, with the fields enclosed by brackets [] replaced by
    4.42 + * your own identifying information:
    4.43 + * "Portions Copyrighted [year] [name of copyright owner]"
    4.44 + *
    4.45 + * Contributor(s):
    4.46 + *
    4.47 + * The Original Software is NetBeans. The Initial Developer of the Original
    4.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
    4.49 + *
    4.50 + * If you wish your version of this file to be governed by only the CDDL
    4.51 + * or only the GPL Version 2, indicate your decision by adding
    4.52 + * "[Contributor] elects to include this software in this distribution
    4.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    4.54 + * single choice of license, a recipient has the option to distribute
    4.55 + * your version of this file under either the CDDL, the GPL Version 2 or
    4.56 + * to extend the choice of license to its licensees as provided above.
    4.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    4.58 + * Version 2 license, then the option applies only if the new code is
    4.59 + * made subject to such option by the copyright holder.
    4.60   */
    4.61  package net.java.html.boot.fx;
    4.62  
    4.63 @@ -27,7 +49,7 @@
    4.64  import javafx.scene.web.WebView;
    4.65  import net.java.html.boot.BrowserBuilder;
    4.66  import net.java.html.js.JavaScriptBody;
    4.67 -import org.apidesign.html.boot.fx.AbstractFXPresenter;
    4.68 +import org.netbeans.html.boot.fx.AbstractFXPresenter;
    4.69  
    4.70  /** Utility methods for working with <em>JavaFX</em> <code>WebView</code>s.
    4.71   *
     5.1 --- a/boot-fx/src/main/java/org/apidesign/html/boot/fx/AbstractFXPresenter.java	Thu Dec 19 17:11:01 2013 +0100
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,168 +0,0 @@
     5.4 -/**
     5.5 - * HTML via Java(tm) Language Bindings
     5.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     5.7 - *
     5.8 - * This program is free software: you can redistribute it and/or modify
     5.9 - * it under the terms of the GNU General Public License as published by
    5.10 - * the Free Software Foundation, version 2 of the License.
    5.11 - *
    5.12 - * This program is distributed in the hope that it will be useful,
    5.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.15 - * GNU General Public License for more details. apidesign.org
    5.16 - * designates this particular file as subject to the
    5.17 - * "Classpath" exception as provided by apidesign.org
    5.18 - * in the License file that accompanied this code.
    5.19 - *
    5.20 - * You should have received a copy of the GNU General Public License
    5.21 - * along with this program. Look for COPYING file in the top folder.
    5.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    5.23 - */
    5.24 -package org.apidesign.html.boot.fx;
    5.25 -
    5.26 -import java.io.BufferedReader;
    5.27 -import java.io.Reader;
    5.28 -import java.net.URL;
    5.29 -import java.util.ArrayList;
    5.30 -import java.util.Arrays;
    5.31 -import java.util.List;
    5.32 -import java.util.logging.Level;
    5.33 -import java.util.logging.Logger;
    5.34 -import javafx.application.Platform;
    5.35 -import javafx.scene.web.WebEngine;
    5.36 -import javafx.scene.web.WebView;
    5.37 -import netscape.javascript.JSObject;
    5.38 -import org.apidesign.html.boot.spi.Fn;
    5.39 -
    5.40 -/**
    5.41 - *
    5.42 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    5.43 - */
    5.44 -public abstract class AbstractFXPresenter implements Fn.Presenter {
    5.45 -    static final Logger LOG = Logger.getLogger(FXPresenter.class.getName());
    5.46 -    protected static int cnt;
    5.47 -    protected List<String> scripts;
    5.48 -    protected Runnable onLoad;
    5.49 -    protected WebEngine engine;
    5.50 -
    5.51 -    @Override
    5.52 -    public Fn defineFn(String code, String... names) {
    5.53 -        StringBuilder sb = new StringBuilder();
    5.54 -        sb.append("(function() {");
    5.55 -        sb.append("  return function(");
    5.56 -        String sep = "";
    5.57 -        for (String n : names) {
    5.58 -            sb.append(sep).append(n);
    5.59 -            sep = ",";
    5.60 -        }
    5.61 -        sb.append(") {\n");
    5.62 -        sb.append(code);
    5.63 -        sb.append("};");
    5.64 -        sb.append("})()");
    5.65 -        if (LOG.isLoggable(Level.FINE)) {
    5.66 -            LOG.log(Level.FINE, 
    5.67 -                "defining function #{0}:\n{1}\n", 
    5.68 -                new Object[] { ++cnt, code }
    5.69 -            );
    5.70 -        }
    5.71 -        JSObject x = (JSObject) engine.executeScript(sb.toString());
    5.72 -        return new JSFn(this, x, cnt);
    5.73 -    }
    5.74 -
    5.75 -    @Override
    5.76 -    public void loadScript(Reader code) throws Exception {
    5.77 -        BufferedReader r = new BufferedReader(code);
    5.78 -        StringBuilder sb = new StringBuilder();
    5.79 -        for (;;) {
    5.80 -            String l = r.readLine();
    5.81 -            if (l == null) {
    5.82 -                break;
    5.83 -            }
    5.84 -            sb.append(l).append('\n');
    5.85 -        }
    5.86 -        final String script = sb.toString();
    5.87 -        if (scripts != null) {
    5.88 -            scripts.add(script);
    5.89 -        }
    5.90 -        engine.executeScript(script);
    5.91 -    }
    5.92 -
    5.93 -    protected final void onPageLoad() {
    5.94 -        if (scripts != null) {
    5.95 -            for (String s : scripts) {
    5.96 -                engine.executeScript(s);
    5.97 -            }
    5.98 -        }
    5.99 -        onLoad.run();
   5.100 -    }
   5.101 -
   5.102 -    @Override
   5.103 -    public void displayPage(final URL resource, final Runnable onLoad) {
   5.104 -        this.onLoad = onLoad;
   5.105 -        final WebView view = findView(resource);
   5.106 -        this.engine = view.getEngine();
   5.107 -        try {
   5.108 -            if (FXInspect.initialize(engine)) {
   5.109 -                scripts = new ArrayList<String>();
   5.110 -            }
   5.111 -        } catch (Throwable ex) {
   5.112 -            ex.printStackTrace();
   5.113 -        }
   5.114 -
   5.115 -        class Run implements Runnable {
   5.116 -
   5.117 -            @Override
   5.118 -            public void run() {
   5.119 -                if (scripts != null) {
   5.120 -                    view.setContextMenuEnabled(true);
   5.121 -                }
   5.122 -                engine.load(resource.toExternalForm());
   5.123 -            }
   5.124 -        }
   5.125 -        Run run = new Run();
   5.126 -        if (Platform.isFxApplicationThread()) {
   5.127 -            run.run();
   5.128 -        } else {
   5.129 -            Platform.runLater(run);
   5.130 -        }
   5.131 -        waitFinished();
   5.132 -    }
   5.133 -
   5.134 -    protected abstract void waitFinished();
   5.135 -
   5.136 -    protected abstract WebView findView(final URL resource);
   5.137 -
   5.138 -    private static final class JSFn extends Fn {
   5.139 -
   5.140 -        private final JSObject fn;
   5.141 -        private static int call;
   5.142 -        private final int id;
   5.143 -
   5.144 -        public JSFn(AbstractFXPresenter p, JSObject fn, int id) {
   5.145 -            super(p);
   5.146 -            this.fn = fn;
   5.147 -            this.id = id;
   5.148 -        }
   5.149 -
   5.150 -        @Override
   5.151 -        public Object invoke(Object thiz, Object... args) throws Exception {
   5.152 -            try {
   5.153 -                if (LOG.isLoggable(Level.FINE)) {
   5.154 -                    LOG.log(Level.FINE, "calling {0} function #{1}", new Object[]{++call, id});
   5.155 -                }
   5.156 -                List<Object> all = new ArrayList<Object>(args.length + 1);
   5.157 -                all.add(thiz == null ? fn : thiz);
   5.158 -                all.addAll(Arrays.asList(args));
   5.159 -                Object ret = fn.call("call", all.toArray()); // NOI18N
   5.160 -                return ret == fn ? null : ret;
   5.161 -            } catch (Error t) {
   5.162 -                t.printStackTrace();
   5.163 -                throw t;
   5.164 -            } catch (Exception t) {
   5.165 -                t.printStackTrace();
   5.166 -                throw t;
   5.167 -            }
   5.168 -        }
   5.169 -    }
   5.170 -    
   5.171 -}
     6.1 --- a/boot-fx/src/main/java/org/apidesign/html/boot/fx/Dbgr.java	Thu Dec 19 17:11:01 2013 +0100
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,66 +0,0 @@
     6.4 -/**
     6.5 - * HTML via Java(tm) Language Bindings
     6.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     6.7 - *
     6.8 - * This program is free software: you can redistribute it and/or modify
     6.9 - * it under the terms of the GNU General Public License as published by
    6.10 - * the Free Software Foundation, version 2 of the License.
    6.11 - *
    6.12 - * This program is distributed in the hope that it will be useful,
    6.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.15 - * GNU General Public License for more details. apidesign.org
    6.16 - * designates this particular file as subject to the
    6.17 - * "Classpath" exception as provided by apidesign.org
    6.18 - * in the License file that accompanied this code.
    6.19 - *
    6.20 - * You should have received a copy of the GNU General Public License
    6.21 - * along with this program. Look for COPYING file in the top folder.
    6.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    6.23 - */
    6.24 -
    6.25 -package org.apidesign.html.boot.fx;
    6.26 -
    6.27 -import java.lang.reflect.Method;
    6.28 -import java.util.logging.Level;
    6.29 -import javafx.scene.web.WebEngine;
    6.30 -import javafx.util.Callback;
    6.31 -import static org.apidesign.html.boot.fx.AbstractFXPresenter.LOG;
    6.32 -
    6.33 -/** Debugger bridge to shield us from propriatory impl APIs.
    6.34 - *
    6.35 - * @author Jaroslav Tulach <jtulach@netbeans.org>
    6.36 - */
    6.37 -final class Dbgr {
    6.38 -    final Object dbg;
    6.39 -    final Method sendMsg;
    6.40 -    
    6.41 -    Dbgr(WebEngine eng, Callback<String,Void> callback) {
    6.42 -        Object d;
    6.43 -        Method m;
    6.44 -        try {
    6.45 -            d = eng.getClass().getMethod("impl_getDebugger").invoke(eng); // NOI18N
    6.46 -            Class<?> debugger = eng.getClass().getClassLoader().loadClass("com.sun.javafx.scene.web.Debugger"); // NOI18N
    6.47 -            debugger.getMethod("setEnabled", boolean.class).invoke(d, true); // NOI18N
    6.48 -            debugger.getMethod("setMessageCallback", Callback.class).invoke(d, callback); // NOI18N
    6.49 -            m = debugger.getMethod("sendMessage", String.class); // NOI18N
    6.50 -        } catch (Exception ex) {
    6.51 -            LOG.log(Level.INFO, null, ex);
    6.52 -            d = null;
    6.53 -            m = null;
    6.54 -        }
    6.55 -        dbg = d;
    6.56 -        sendMsg = m;
    6.57 -    }
    6.58 -
    6.59 -    void sendMessage(String msg) {
    6.60 -        try {
    6.61 -            if (dbg != null) {
    6.62 -                sendMsg.invoke(dbg, msg);
    6.63 -            }
    6.64 -        } catch (Exception ex) {
    6.65 -            LOG.log(Level.INFO, null, ex);
    6.66 -        }
    6.67 -    }
    6.68 -    
    6.69 -}
     7.1 --- a/boot-fx/src/main/java/org/apidesign/html/boot/fx/FXBrwsr.java	Thu Dec 19 17:11:01 2013 +0100
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,171 +0,0 @@
     7.4 -/**
     7.5 - * HTML via Java(tm) Language Bindings
     7.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     7.7 - *
     7.8 - * This program is free software: you can redistribute it and/or modify
     7.9 - * it under the terms of the GNU General Public License as published by
    7.10 - * the Free Software Foundation, version 2 of the License.
    7.11 - *
    7.12 - * This program is distributed in the hope that it will be useful,
    7.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.15 - * GNU General Public License for more details. apidesign.org
    7.16 - * designates this particular file as subject to the
    7.17 - * "Classpath" exception as provided by apidesign.org
    7.18 - * in the License file that accompanied this code.
    7.19 - *
    7.20 - * You should have received a copy of the GNU General Public License
    7.21 - * along with this program. Look for COPYING file in the top folder.
    7.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    7.23 - */
    7.24 -package org.apidesign.html.boot.fx;
    7.25 -
    7.26 -import java.net.URL;
    7.27 -import java.util.concurrent.CountDownLatch;
    7.28 -import java.util.concurrent.Executors;
    7.29 -import java.util.logging.Level;
    7.30 -import java.util.logging.Logger;
    7.31 -import javafx.application.Application;
    7.32 -import javafx.application.Platform;
    7.33 -import javafx.beans.value.ChangeListener;
    7.34 -import javafx.beans.value.ObservableValue;
    7.35 -import javafx.concurrent.Worker;
    7.36 -import javafx.event.ActionEvent;
    7.37 -import javafx.event.EventHandler;
    7.38 -import javafx.geometry.Insets;
    7.39 -import javafx.geometry.Pos;
    7.40 -import javafx.scene.Scene;
    7.41 -import javafx.scene.control.Button;
    7.42 -import javafx.scene.layout.BorderPane;
    7.43 -import javafx.scene.layout.VBox;
    7.44 -import javafx.scene.text.Text;
    7.45 -import javafx.scene.web.WebEvent;
    7.46 -import javafx.scene.web.WebView;
    7.47 -import javafx.stage.Modality;
    7.48 -import javafx.stage.Stage;
    7.49 -
    7.50 -/** This is an implementation class, use {@link BrowserBuilder} API. Just
    7.51 - * include this JAR on classpath and the {@link BrowserBuilder} API will find
    7.52 - * this implementation automatically.
    7.53 - */
    7.54 -public class FXBrwsr extends Application {
    7.55 -    private static final Logger LOG = Logger.getLogger(FXBrwsr.class.getName());
    7.56 -    private static FXBrwsr INSTANCE;
    7.57 -    private static final CountDownLatch FINISHED = new CountDownLatch(1);
    7.58 -    private BorderPane root;
    7.59 -
    7.60 -    public static synchronized WebView findWebView(final URL url, final FXPresenter onLoad) {
    7.61 -        if (INSTANCE == null) {
    7.62 -            Executors.newFixedThreadPool(1).submit(new Runnable() {
    7.63 -                @Override
    7.64 -                public void run() {
    7.65 -                    try {
    7.66 -                        FXBrwsr.launch(FXBrwsr.class);
    7.67 -                    } catch (Throwable ex) {
    7.68 -                        ex.printStackTrace();
    7.69 -                    } finally {
    7.70 -                        FINISHED.countDown();
    7.71 -                    }
    7.72 -                }
    7.73 -            });
    7.74 -        }
    7.75 -        while (INSTANCE == null) {
    7.76 -            try {
    7.77 -                FXBrwsr.class.wait();
    7.78 -            } catch (InterruptedException ex) {
    7.79 -                // wait more
    7.80 -            }
    7.81 -        }
    7.82 -        if (!Platform.isFxApplicationThread()) {
    7.83 -            final WebView[] arr = {null};
    7.84 -            final CountDownLatch waitForResult = new CountDownLatch(1);
    7.85 -            Platform.runLater(new Runnable() {
    7.86 -                @Override
    7.87 -                public void run() {
    7.88 -                    arr[0] = INSTANCE.newView(url, onLoad);
    7.89 -                    waitForResult.countDown();
    7.90 -                }
    7.91 -            });
    7.92 -            for (;;) {
    7.93 -                try {
    7.94 -                    waitForResult.await();
    7.95 -                    break;
    7.96 -                } catch (InterruptedException ex) {
    7.97 -                    LOG.log(Level.INFO, null, ex);
    7.98 -                }
    7.99 -            }
   7.100 -            return arr[0];
   7.101 -        } else {
   7.102 -            return INSTANCE.newView(url, onLoad);
   7.103 -        }
   7.104 -    }
   7.105 -
   7.106 -    @Override
   7.107 -    public void start(Stage primaryStage) throws Exception {
   7.108 -        synchronized (FXBrwsr.class) {
   7.109 -            INSTANCE = this;
   7.110 -            FXBrwsr.class.notifyAll();
   7.111 -        }
   7.112 -        BorderPane r = new BorderPane();
   7.113 -        Scene scene = new Scene(r, 800, 600);
   7.114 -        primaryStage.setScene(scene);
   7.115 -        primaryStage.show();
   7.116 -        this.root = r;
   7.117 -    }
   7.118 -
   7.119 -    private WebView newView(final URL url, final FXPresenter onLoad) {
   7.120 -        final WebView view = new WebView();
   7.121 -        view.setContextMenuEnabled(false);
   7.122 -        view.getEngine().setOnAlert(new EventHandler<WebEvent<String>>() {
   7.123 -            @Override
   7.124 -            public void handle(WebEvent<String> t) {
   7.125 -                final Stage dialogStage = new Stage();
   7.126 -                dialogStage.initModality(Modality.WINDOW_MODAL);
   7.127 -                dialogStage.setTitle("Warning");
   7.128 -                final Button button = new Button("Close");
   7.129 -                final Text text = new Text(t.getData());
   7.130 -                VBox box = new VBox();
   7.131 -                box.setAlignment(Pos.CENTER);
   7.132 -                box.setSpacing(10);
   7.133 -                box.setPadding(new Insets(10));
   7.134 -                box.getChildren().addAll(text, button);
   7.135 -                dialogStage.setScene(new Scene(box));
   7.136 -                button.setCancelButton(true);
   7.137 -                button.setOnAction(new EventHandler<ActionEvent>() {
   7.138 -                    @Override
   7.139 -                    public void handle(ActionEvent t) {
   7.140 -                        dialogStage.close();
   7.141 -                    }
   7.142 -                });
   7.143 -                dialogStage.centerOnScreen();
   7.144 -                dialogStage.showAndWait();
   7.145 -            }
   7.146 -        });
   7.147 -        root.setCenter(view);
   7.148 -        final Worker<Void> w = view.getEngine().getLoadWorker();
   7.149 -        w.stateProperty().addListener(new ChangeListener<Worker.State>() {
   7.150 -            @Override
   7.151 -            public void changed(ObservableValue<? extends Worker.State> ov, Worker.State t, Worker.State newState) {
   7.152 -                if (newState.equals(Worker.State.SUCCEEDED)) {
   7.153 -                    onLoad.onPageLoad();
   7.154 -                }
   7.155 -                if (newState.equals(Worker.State.FAILED)) {
   7.156 -                    throw new IllegalStateException("Failed to load " + url);
   7.157 -                }
   7.158 -            }
   7.159 -        });
   7.160 -        return view;
   7.161 -    }
   7.162 -
   7.163 -    static void waitFinished() {
   7.164 -        for (;;) {
   7.165 -            try {
   7.166 -                FINISHED.await();
   7.167 -                break;
   7.168 -            } catch (InterruptedException ex) {
   7.169 -                LOG.log(Level.INFO, null, ex);
   7.170 -            }
   7.171 -        }
   7.172 -    }
   7.173 -    
   7.174 -}
     8.1 --- a/boot-fx/src/main/java/org/apidesign/html/boot/fx/FXInspect.java	Thu Dec 19 17:11:01 2013 +0100
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,112 +0,0 @@
     8.4 -/**
     8.5 - * HTML via Java(tm) Language Bindings
     8.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     8.7 - *
     8.8 - * This program is free software: you can redistribute it and/or modify
     8.9 - * it under the terms of the GNU General Public License as published by
    8.10 - * the Free Software Foundation, version 2 of the License.
    8.11 - *
    8.12 - * This program is distributed in the hope that it will be useful,
    8.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.15 - * GNU General Public License for more details. apidesign.org
    8.16 - * designates this particular file as subject to the
    8.17 - * "Classpath" exception as provided by apidesign.org
    8.18 - * in the License file that accompanied this code.
    8.19 - *
    8.20 - * You should have received a copy of the GNU General Public License
    8.21 - * along with this program. Look for COPYING file in the top folder.
    8.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    8.23 - */
    8.24 -package org.apidesign.html.boot.fx;
    8.25 -
    8.26 -import java.io.IOException;
    8.27 -import java.io.ObjectInputStream;
    8.28 -import java.io.ObjectOutputStream;
    8.29 -import java.net.InetAddress;
    8.30 -import java.net.Socket;
    8.31 -import java.nio.charset.StandardCharsets;
    8.32 -import java.util.logging.Level;
    8.33 -import java.util.logging.Logger;
    8.34 -import javafx.application.Platform;
    8.35 -import javafx.scene.web.WebEngine;
    8.36 -import javafx.util.Callback;
    8.37 -
    8.38 -/**
    8.39 - *
    8.40 - * @author Jaroslav Tulach <jtulach@netbeans.org>
    8.41 - */
    8.42 -final class FXInspect implements Runnable {
    8.43 -    private static final Logger LOG = Logger.getLogger(FXInspect.class.getName());
    8.44 -    
    8.45 -    
    8.46 -    private final WebEngine engine;
    8.47 -    private final ObjectInputStream input;
    8.48 -    private Dbgr dbg;
    8.49 -    
    8.50 -    private FXInspect(WebEngine engine, int port) throws IOException {
    8.51 -        this.engine = engine;
    8.52 -        
    8.53 -        Socket socket = new Socket(InetAddress.getByName(null), port);
    8.54 -        ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
    8.55 -        this.input = new ObjectInputStream(socket.getInputStream());
    8.56 -        initializeDebugger(output);
    8.57 -    }
    8.58 -    
    8.59 -    static boolean initialize(WebEngine engine) {
    8.60 -        final int inspectPort = Integer.getInteger("netbeans.inspect.port", -1); // NOI18N
    8.61 -        if (inspectPort != -1) {
    8.62 -            try {
    8.63 -                FXInspect inspector = new FXInspect(engine, inspectPort);
    8.64 -                Thread t = new Thread(inspector, "FX<->NetBeans Inspector");
    8.65 -                t.start();
    8.66 -                return true;
    8.67 -            } catch (IOException ex) {
    8.68 -                LOG.log(Level.INFO, "Cannot connect to NetBeans IDE to port " + inspectPort, ex); // NOI18N
    8.69 -            }
    8.70 -        }
    8.71 -        return false;
    8.72 -    }
    8.73 -    
    8.74 -    private void initializeDebugger(final ObjectOutputStream output) {
    8.75 -        Platform.runLater(new Runnable() {
    8.76 -            @Override
    8.77 -            public void run() {
    8.78 -                dbg = new Dbgr(engine, new Callback<String,Void>() {
    8.79 -                    @Override
    8.80 -                    public Void call(String message) {
    8.81 -                        try {
    8.82 -                            byte[] bytes = message.getBytes(StandardCharsets.UTF_8);
    8.83 -                            output.writeInt(bytes.length);
    8.84 -                            output.write(bytes);
    8.85 -                            output.flush();
    8.86 -                        } catch (IOException ioex) {
    8.87 -                            ioex.printStackTrace();
    8.88 -                        }
    8.89 -                        return null;
    8.90 -                    }
    8.91 -                });
    8.92 -            }
    8.93 -        });
    8.94 -    }
    8.95 -
    8.96 -    @Override
    8.97 -    public void run() {
    8.98 -        try {
    8.99 -            while (true) {
   8.100 -                int length = input.readInt();
   8.101 -                byte[] bytes = new byte[length];
   8.102 -                input.readFully(bytes);
   8.103 -                final String message = new String(bytes, StandardCharsets.UTF_8);
   8.104 -                Platform.runLater(new Runnable() {
   8.105 -                    @Override
   8.106 -                    public void run() {
   8.107 -                        dbg.sendMessage(message);
   8.108 -                    }
   8.109 -                });
   8.110 -            }
   8.111 -        } catch (IOException ex) {
   8.112 -            LOG.log(Level.WARNING, null, ex);
   8.113 -        }
   8.114 -    }
   8.115 -}
     9.1 --- a/boot-fx/src/main/java/org/apidesign/html/boot/fx/FXPresenter.java	Thu Dec 19 17:11:01 2013 +0100
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,76 +0,0 @@
     9.4 -/**
     9.5 - * HTML via Java(tm) Language Bindings
     9.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     9.7 - *
     9.8 - * This program is free software: you can redistribute it and/or modify
     9.9 - * it under the terms of the GNU General Public License as published by
    9.10 - * the Free Software Foundation, version 2 of the License.
    9.11 - *
    9.12 - * This program is distributed in the hope that it will be useful,
    9.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.15 - * GNU General Public License for more details. apidesign.org
    9.16 - * designates this particular file as subject to the
    9.17 - * "Classpath" exception as provided by apidesign.org
    9.18 - * in the License file that accompanied this code.
    9.19 - *
    9.20 - * You should have received a copy of the GNU General Public License
    9.21 - * along with this program. Look for COPYING file in the top folder.
    9.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    9.23 - */
    9.24 -package org.apidesign.html.boot.fx;
    9.25 -
    9.26 -import java.io.BufferedReader;
    9.27 -import java.io.File;
    9.28 -import java.io.Reader;
    9.29 -import java.lang.reflect.Method;
    9.30 -import java.net.URL;
    9.31 -import java.net.URLClassLoader;
    9.32 -import java.util.ArrayList;
    9.33 -import java.util.Arrays;
    9.34 -import java.util.List;
    9.35 -import java.util.logging.Level;
    9.36 -import java.util.logging.Logger;
    9.37 -import javafx.application.Platform;
    9.38 -import javafx.scene.web.WebEngine;
    9.39 -import javafx.scene.web.WebView;
    9.40 -import net.java.html.boot.BrowserBuilder;
    9.41 -import netscape.javascript.JSObject;
    9.42 -import org.apidesign.html.boot.spi.Fn;
    9.43 -import org.openide.util.lookup.ServiceProvider;
    9.44 -
    9.45 -/** This is an implementation class, use {@link BrowserBuilder} API. Just
    9.46 - * include this JAR on classpath and the {@link BrowserBuilder} API will find
    9.47 - * this implementation automatically.
    9.48 - *
    9.49 - * @author Jaroslav Tulach <jtulach@netbeans.org>
    9.50 - */
    9.51 -@ServiceProvider(service = Fn.Presenter.class)
    9.52 -public final class FXPresenter extends AbstractFXPresenter {
    9.53 -    static {
    9.54 -        try {
    9.55 -            try {
    9.56 -                Class<?> c = Class.forName("javafx.application.Platform");
    9.57 -                // OK, on classpath
    9.58 -            } catch (ClassNotFoundException classNotFoundException) {
    9.59 -                Method m = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
    9.60 -                m.setAccessible(true);
    9.61 -                File f = new File(System.getProperty("java.home"), "lib/jfxrt.jar");
    9.62 -                if (f.exists()) {
    9.63 -                    URL l = f.toURI().toURL();
    9.64 -                    m.invoke(ClassLoader.getSystemClassLoader(), l);
    9.65 -                }
    9.66 -            }
    9.67 -        } catch (Exception ex) {
    9.68 -            throw new LinkageError("Can't add jfxrt.jar on the classpath", ex);
    9.69 -        }
    9.70 -    }
    9.71 -
    9.72 -    protected void waitFinished() {
    9.73 -        FXBrwsr.waitFinished();
    9.74 -    }
    9.75 -
    9.76 -    protected WebView findView(final URL resource) {
    9.77 -        return FXBrwsr.findWebView(resource, this);
    9.78 -    }
    9.79 -}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/AbstractFXPresenter.java	Tue Jan 07 08:21:57 2014 +0100
    10.3 @@ -0,0 +1,190 @@
    10.4 +/**
    10.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    10.6 + *
    10.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    10.8 + *
    10.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   10.10 + * Other names may be trademarks of their respective owners.
   10.11 + *
   10.12 + * The contents of this file are subject to the terms of either the GNU
   10.13 + * General Public License Version 2 only ("GPL") or the Common
   10.14 + * Development and Distribution License("CDDL") (collectively, the
   10.15 + * "License"). You may not use this file except in compliance with the
   10.16 + * License. You can obtain a copy of the License at
   10.17 + * http://www.netbeans.org/cddl-gplv2.html
   10.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   10.19 + * specific language governing permissions and limitations under the
   10.20 + * License.  When distributing the software, include this License Header
   10.21 + * Notice in each file and include the License file at
   10.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   10.23 + * particular file as subject to the "Classpath" exception as provided
   10.24 + * by Oracle in the GPL Version 2 section of the License file that
   10.25 + * accompanied this code. If applicable, add the following below the
   10.26 + * License Header, with the fields enclosed by brackets [] replaced by
   10.27 + * your own identifying information:
   10.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   10.29 + *
   10.30 + * Contributor(s):
   10.31 + *
   10.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   10.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   10.34 + *
   10.35 + * If you wish your version of this file to be governed by only the CDDL
   10.36 + * or only the GPL Version 2, indicate your decision by adding
   10.37 + * "[Contributor] elects to include this software in this distribution
   10.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   10.39 + * single choice of license, a recipient has the option to distribute
   10.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   10.41 + * to extend the choice of license to its licensees as provided above.
   10.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   10.43 + * Version 2 license, then the option applies only if the new code is
   10.44 + * made subject to such option by the copyright holder.
   10.45 + */
   10.46 +package org.netbeans.html.boot.fx;
   10.47 +
   10.48 +import java.io.BufferedReader;
   10.49 +import java.io.Reader;
   10.50 +import java.net.URL;
   10.51 +import java.util.ArrayList;
   10.52 +import java.util.Arrays;
   10.53 +import java.util.List;
   10.54 +import java.util.logging.Level;
   10.55 +import java.util.logging.Logger;
   10.56 +import javafx.application.Platform;
   10.57 +import javafx.scene.web.WebEngine;
   10.58 +import javafx.scene.web.WebView;
   10.59 +import netscape.javascript.JSObject;
   10.60 +import org.apidesign.html.boot.spi.Fn;
   10.61 +
   10.62 +/**
   10.63 + *
   10.64 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   10.65 + */
   10.66 +public abstract class AbstractFXPresenter implements Fn.Presenter {
   10.67 +    static final Logger LOG = Logger.getLogger(FXPresenter.class.getName());
   10.68 +    protected static int cnt;
   10.69 +    protected List<String> scripts;
   10.70 +    protected Runnable onLoad;
   10.71 +    protected WebEngine engine;
   10.72 +
   10.73 +    @Override
   10.74 +    public Fn defineFn(String code, String... names) {
   10.75 +        StringBuilder sb = new StringBuilder();
   10.76 +        sb.append("(function() {");
   10.77 +        sb.append("  return function(");
   10.78 +        String sep = "";
   10.79 +        for (String n : names) {
   10.80 +            sb.append(sep).append(n);
   10.81 +            sep = ",";
   10.82 +        }
   10.83 +        sb.append(") {\n");
   10.84 +        sb.append(code);
   10.85 +        sb.append("};");
   10.86 +        sb.append("})()");
   10.87 +        if (LOG.isLoggable(Level.FINE)) {
   10.88 +            LOG.log(Level.FINE, 
   10.89 +                "defining function #{0}:\n{1}\n", 
   10.90 +                new Object[] { ++cnt, code }
   10.91 +            );
   10.92 +        }
   10.93 +        JSObject x = (JSObject) engine.executeScript(sb.toString());
   10.94 +        return new JSFn(this, x, cnt);
   10.95 +    }
   10.96 +
   10.97 +    @Override
   10.98 +    public void loadScript(Reader code) throws Exception {
   10.99 +        BufferedReader r = new BufferedReader(code);
  10.100 +        StringBuilder sb = new StringBuilder();
  10.101 +        for (;;) {
  10.102 +            String l = r.readLine();
  10.103 +            if (l == null) {
  10.104 +                break;
  10.105 +            }
  10.106 +            sb.append(l).append('\n');
  10.107 +        }
  10.108 +        final String script = sb.toString();
  10.109 +        if (scripts != null) {
  10.110 +            scripts.add(script);
  10.111 +        }
  10.112 +        engine.executeScript(script);
  10.113 +    }
  10.114 +
  10.115 +    protected final void onPageLoad() {
  10.116 +        if (scripts != null) {
  10.117 +            for (String s : scripts) {
  10.118 +                engine.executeScript(s);
  10.119 +            }
  10.120 +        }
  10.121 +        onLoad.run();
  10.122 +    }
  10.123 +
  10.124 +    @Override
  10.125 +    public void displayPage(final URL resource, final Runnable onLoad) {
  10.126 +        this.onLoad = onLoad;
  10.127 +        final WebView view = findView(resource);
  10.128 +        this.engine = view.getEngine();
  10.129 +        try {
  10.130 +            if (FXInspect.initialize(engine)) {
  10.131 +                scripts = new ArrayList<String>();
  10.132 +            }
  10.133 +        } catch (Throwable ex) {
  10.134 +            ex.printStackTrace();
  10.135 +        }
  10.136 +
  10.137 +        class Run implements Runnable {
  10.138 +
  10.139 +            @Override
  10.140 +            public void run() {
  10.141 +                if (scripts != null) {
  10.142 +                    view.setContextMenuEnabled(true);
  10.143 +                }
  10.144 +                engine.load(resource.toExternalForm());
  10.145 +            }
  10.146 +        }
  10.147 +        Run run = new Run();
  10.148 +        if (Platform.isFxApplicationThread()) {
  10.149 +            run.run();
  10.150 +        } else {
  10.151 +            Platform.runLater(run);
  10.152 +        }
  10.153 +        waitFinished();
  10.154 +    }
  10.155 +
  10.156 +    protected abstract void waitFinished();
  10.157 +
  10.158 +    protected abstract WebView findView(final URL resource);
  10.159 +
  10.160 +    private static final class JSFn extends Fn {
  10.161 +
  10.162 +        private final JSObject fn;
  10.163 +        private static int call;
  10.164 +        private final int id;
  10.165 +
  10.166 +        public JSFn(AbstractFXPresenter p, JSObject fn, int id) {
  10.167 +            super(p);
  10.168 +            this.fn = fn;
  10.169 +            this.id = id;
  10.170 +        }
  10.171 +
  10.172 +        @Override
  10.173 +        public Object invoke(Object thiz, Object... args) throws Exception {
  10.174 +            try {
  10.175 +                if (LOG.isLoggable(Level.FINE)) {
  10.176 +                    LOG.log(Level.FINE, "calling {0} function #{1}", new Object[]{++call, id});
  10.177 +                }
  10.178 +                List<Object> all = new ArrayList<Object>(args.length + 1);
  10.179 +                all.add(thiz == null ? fn : thiz);
  10.180 +                all.addAll(Arrays.asList(args));
  10.181 +                Object ret = fn.call("call", all.toArray()); // NOI18N
  10.182 +                return ret == fn ? null : ret;
  10.183 +            } catch (Error t) {
  10.184 +                t.printStackTrace();
  10.185 +                throw t;
  10.186 +            } catch (Exception t) {
  10.187 +                t.printStackTrace();
  10.188 +                throw t;
  10.189 +            }
  10.190 +        }
  10.191 +    }
  10.192 +    
  10.193 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/Dbgr.java	Tue Jan 07 08:21:57 2014 +0100
    11.3 @@ -0,0 +1,87 @@
    11.4 +/**
    11.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    11.6 + *
    11.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    11.8 + *
    11.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   11.10 + * Other names may be trademarks of their respective owners.
   11.11 + *
   11.12 + * The contents of this file are subject to the terms of either the GNU
   11.13 + * General Public License Version 2 only ("GPL") or the Common
   11.14 + * Development and Distribution License("CDDL") (collectively, the
   11.15 + * "License"). You may not use this file except in compliance with the
   11.16 + * License. You can obtain a copy of the License at
   11.17 + * http://www.netbeans.org/cddl-gplv2.html
   11.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   11.19 + * specific language governing permissions and limitations under the
   11.20 + * License.  When distributing the software, include this License Header
   11.21 + * Notice in each file and include the License file at
   11.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   11.23 + * particular file as subject to the "Classpath" exception as provided
   11.24 + * by Oracle in the GPL Version 2 section of the License file that
   11.25 + * accompanied this code. If applicable, add the following below the
   11.26 + * License Header, with the fields enclosed by brackets [] replaced by
   11.27 + * your own identifying information:
   11.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   11.29 + *
   11.30 + * Contributor(s):
   11.31 + *
   11.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   11.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   11.34 + *
   11.35 + * If you wish your version of this file to be governed by only the CDDL
   11.36 + * or only the GPL Version 2, indicate your decision by adding
   11.37 + * "[Contributor] elects to include this software in this distribution
   11.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   11.39 + * single choice of license, a recipient has the option to distribute
   11.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   11.41 + * to extend the choice of license to its licensees as provided above.
   11.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   11.43 + * Version 2 license, then the option applies only if the new code is
   11.44 + * made subject to such option by the copyright holder.
   11.45 + */
   11.46 +package org.netbeans.html.boot.fx;
   11.47 +
   11.48 +import java.lang.reflect.Method;
   11.49 +import java.util.logging.Level;
   11.50 +import javafx.scene.web.WebEngine;
   11.51 +import javafx.util.Callback;
   11.52 +import static org.netbeans.html.boot.fx.AbstractFXPresenter.LOG;
   11.53 +
   11.54 +/** Debugger bridge to shield us from propriatory impl APIs.
   11.55 + *
   11.56 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   11.57 + */
   11.58 +final class Dbgr {
   11.59 +    final Object dbg;
   11.60 +    final Method sendMsg;
   11.61 +    
   11.62 +    Dbgr(WebEngine eng, Callback<String,Void> callback) {
   11.63 +        Object d;
   11.64 +        Method m;
   11.65 +        try {
   11.66 +            d = eng.getClass().getMethod("impl_getDebugger").invoke(eng); // NOI18N
   11.67 +            Class<?> debugger = eng.getClass().getClassLoader().loadClass("com.sun.javafx.scene.web.Debugger"); // NOI18N
   11.68 +            debugger.getMethod("setEnabled", boolean.class).invoke(d, true); // NOI18N
   11.69 +            debugger.getMethod("setMessageCallback", Callback.class).invoke(d, callback); // NOI18N
   11.70 +            m = debugger.getMethod("sendMessage", String.class); // NOI18N
   11.71 +        } catch (Exception ex) {
   11.72 +            LOG.log(Level.INFO, null, ex);
   11.73 +            d = null;
   11.74 +            m = null;
   11.75 +        }
   11.76 +        dbg = d;
   11.77 +        sendMsg = m;
   11.78 +    }
   11.79 +
   11.80 +    void sendMessage(String msg) {
   11.81 +        try {
   11.82 +            if (dbg != null) {
   11.83 +                sendMsg.invoke(dbg, msg);
   11.84 +            }
   11.85 +        } catch (Exception ex) {
   11.86 +            LOG.log(Level.INFO, null, ex);
   11.87 +        }
   11.88 +    }
   11.89 +    
   11.90 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXBrwsr.java	Tue Jan 07 08:21:57 2014 +0100
    12.3 @@ -0,0 +1,193 @@
    12.4 +/**
    12.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    12.6 + *
    12.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    12.8 + *
    12.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   12.10 + * Other names may be trademarks of their respective owners.
   12.11 + *
   12.12 + * The contents of this file are subject to the terms of either the GNU
   12.13 + * General Public License Version 2 only ("GPL") or the Common
   12.14 + * Development and Distribution License("CDDL") (collectively, the
   12.15 + * "License"). You may not use this file except in compliance with the
   12.16 + * License. You can obtain a copy of the License at
   12.17 + * http://www.netbeans.org/cddl-gplv2.html
   12.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   12.19 + * specific language governing permissions and limitations under the
   12.20 + * License.  When distributing the software, include this License Header
   12.21 + * Notice in each file and include the License file at
   12.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   12.23 + * particular file as subject to the "Classpath" exception as provided
   12.24 + * by Oracle in the GPL Version 2 section of the License file that
   12.25 + * accompanied this code. If applicable, add the following below the
   12.26 + * License Header, with the fields enclosed by brackets [] replaced by
   12.27 + * your own identifying information:
   12.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   12.29 + *
   12.30 + * Contributor(s):
   12.31 + *
   12.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   12.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   12.34 + *
   12.35 + * If you wish your version of this file to be governed by only the CDDL
   12.36 + * or only the GPL Version 2, indicate your decision by adding
   12.37 + * "[Contributor] elects to include this software in this distribution
   12.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   12.39 + * single choice of license, a recipient has the option to distribute
   12.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   12.41 + * to extend the choice of license to its licensees as provided above.
   12.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   12.43 + * Version 2 license, then the option applies only if the new code is
   12.44 + * made subject to such option by the copyright holder.
   12.45 + */
   12.46 +package org.netbeans.html.boot.fx;
   12.47 +
   12.48 +import java.net.URL;
   12.49 +import java.util.concurrent.CountDownLatch;
   12.50 +import java.util.concurrent.Executors;
   12.51 +import java.util.logging.Level;
   12.52 +import java.util.logging.Logger;
   12.53 +import javafx.application.Application;
   12.54 +import javafx.application.Platform;
   12.55 +import javafx.beans.value.ChangeListener;
   12.56 +import javafx.beans.value.ObservableValue;
   12.57 +import javafx.concurrent.Worker;
   12.58 +import javafx.event.ActionEvent;
   12.59 +import javafx.event.EventHandler;
   12.60 +import javafx.geometry.Insets;
   12.61 +import javafx.geometry.Pos;
   12.62 +import javafx.scene.Scene;
   12.63 +import javafx.scene.control.Button;
   12.64 +import javafx.scene.layout.BorderPane;
   12.65 +import javafx.scene.layout.VBox;
   12.66 +import javafx.scene.text.Text;
   12.67 +import javafx.scene.web.WebEvent;
   12.68 +import javafx.scene.web.WebView;
   12.69 +import javafx.stage.Modality;
   12.70 +import javafx.stage.Stage;
   12.71 +
   12.72 +/** This is an implementation class, use {@link BrowserBuilder} API. Just
   12.73 + * include this JAR on classpath and the {@link BrowserBuilder} API will find
   12.74 + * this implementation automatically.
   12.75 + */
   12.76 +public class FXBrwsr extends Application {
   12.77 +    private static final Logger LOG = Logger.getLogger(FXBrwsr.class.getName());
   12.78 +    private static FXBrwsr INSTANCE;
   12.79 +    private static final CountDownLatch FINISHED = new CountDownLatch(1);
   12.80 +    private BorderPane root;
   12.81 +
   12.82 +    public static synchronized WebView findWebView(final URL url, final FXPresenter onLoad) {
   12.83 +        if (INSTANCE == null) {
   12.84 +            Executors.newFixedThreadPool(1).submit(new Runnable() {
   12.85 +                @Override
   12.86 +                public void run() {
   12.87 +                    try {
   12.88 +                        FXBrwsr.launch(FXBrwsr.class);
   12.89 +                    } catch (Throwable ex) {
   12.90 +                        ex.printStackTrace();
   12.91 +                    } finally {
   12.92 +                        FINISHED.countDown();
   12.93 +                    }
   12.94 +                }
   12.95 +            });
   12.96 +        }
   12.97 +        while (INSTANCE == null) {
   12.98 +            try {
   12.99 +                FXBrwsr.class.wait();
  12.100 +            } catch (InterruptedException ex) {
  12.101 +                // wait more
  12.102 +            }
  12.103 +        }
  12.104 +        if (!Platform.isFxApplicationThread()) {
  12.105 +            final WebView[] arr = {null};
  12.106 +            final CountDownLatch waitForResult = new CountDownLatch(1);
  12.107 +            Platform.runLater(new Runnable() {
  12.108 +                @Override
  12.109 +                public void run() {
  12.110 +                    arr[0] = INSTANCE.newView(url, onLoad);
  12.111 +                    waitForResult.countDown();
  12.112 +                }
  12.113 +            });
  12.114 +            for (;;) {
  12.115 +                try {
  12.116 +                    waitForResult.await();
  12.117 +                    break;
  12.118 +                } catch (InterruptedException ex) {
  12.119 +                    LOG.log(Level.INFO, null, ex);
  12.120 +                }
  12.121 +            }
  12.122 +            return arr[0];
  12.123 +        } else {
  12.124 +            return INSTANCE.newView(url, onLoad);
  12.125 +        }
  12.126 +    }
  12.127 +
  12.128 +    @Override
  12.129 +    public void start(Stage primaryStage) throws Exception {
  12.130 +        synchronized (FXBrwsr.class) {
  12.131 +            INSTANCE = this;
  12.132 +            FXBrwsr.class.notifyAll();
  12.133 +        }
  12.134 +        BorderPane r = new BorderPane();
  12.135 +        Scene scene = new Scene(r, 800, 600);
  12.136 +        primaryStage.setScene(scene);
  12.137 +        primaryStage.show();
  12.138 +        this.root = r;
  12.139 +    }
  12.140 +
  12.141 +    private WebView newView(final URL url, final FXPresenter onLoad) {
  12.142 +        final WebView view = new WebView();
  12.143 +        view.setContextMenuEnabled(false);
  12.144 +        view.getEngine().setOnAlert(new EventHandler<WebEvent<String>>() {
  12.145 +            @Override
  12.146 +            public void handle(WebEvent<String> t) {
  12.147 +                final Stage dialogStage = new Stage();
  12.148 +                dialogStage.initModality(Modality.WINDOW_MODAL);
  12.149 +                dialogStage.setTitle("Warning");
  12.150 +                final Button button = new Button("Close");
  12.151 +                final Text text = new Text(t.getData());
  12.152 +                VBox box = new VBox();
  12.153 +                box.setAlignment(Pos.CENTER);
  12.154 +                box.setSpacing(10);
  12.155 +                box.setPadding(new Insets(10));
  12.156 +                box.getChildren().addAll(text, button);
  12.157 +                dialogStage.setScene(new Scene(box));
  12.158 +                button.setCancelButton(true);
  12.159 +                button.setOnAction(new EventHandler<ActionEvent>() {
  12.160 +                    @Override
  12.161 +                    public void handle(ActionEvent t) {
  12.162 +                        dialogStage.close();
  12.163 +                    }
  12.164 +                });
  12.165 +                dialogStage.centerOnScreen();
  12.166 +                dialogStage.showAndWait();
  12.167 +            }
  12.168 +        });
  12.169 +        root.setCenter(view);
  12.170 +        final Worker<Void> w = view.getEngine().getLoadWorker();
  12.171 +        w.stateProperty().addListener(new ChangeListener<Worker.State>() {
  12.172 +            @Override
  12.173 +            public void changed(ObservableValue<? extends Worker.State> ov, Worker.State t, Worker.State newState) {
  12.174 +                if (newState.equals(Worker.State.SUCCEEDED)) {
  12.175 +                    onLoad.onPageLoad();
  12.176 +                }
  12.177 +                if (newState.equals(Worker.State.FAILED)) {
  12.178 +                    throw new IllegalStateException("Failed to load " + url);
  12.179 +                }
  12.180 +            }
  12.181 +        });
  12.182 +        return view;
  12.183 +    }
  12.184 +
  12.185 +    static void waitFinished() {
  12.186 +        for (;;) {
  12.187 +            try {
  12.188 +                FINISHED.await();
  12.189 +                break;
  12.190 +            } catch (InterruptedException ex) {
  12.191 +                LOG.log(Level.INFO, null, ex);
  12.192 +            }
  12.193 +        }
  12.194 +    }
  12.195 +    
  12.196 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXInspect.java	Tue Jan 07 08:21:57 2014 +0100
    13.3 @@ -0,0 +1,134 @@
    13.4 +/**
    13.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    13.6 + *
    13.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    13.8 + *
    13.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   13.10 + * Other names may be trademarks of their respective owners.
   13.11 + *
   13.12 + * The contents of this file are subject to the terms of either the GNU
   13.13 + * General Public License Version 2 only ("GPL") or the Common
   13.14 + * Development and Distribution License("CDDL") (collectively, the
   13.15 + * "License"). You may not use this file except in compliance with the
   13.16 + * License. You can obtain a copy of the License at
   13.17 + * http://www.netbeans.org/cddl-gplv2.html
   13.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   13.19 + * specific language governing permissions and limitations under the
   13.20 + * License.  When distributing the software, include this License Header
   13.21 + * Notice in each file and include the License file at
   13.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   13.23 + * particular file as subject to the "Classpath" exception as provided
   13.24 + * by Oracle in the GPL Version 2 section of the License file that
   13.25 + * accompanied this code. If applicable, add the following below the
   13.26 + * License Header, with the fields enclosed by brackets [] replaced by
   13.27 + * your own identifying information:
   13.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   13.29 + *
   13.30 + * Contributor(s):
   13.31 + *
   13.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   13.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   13.34 + *
   13.35 + * If you wish your version of this file to be governed by only the CDDL
   13.36 + * or only the GPL Version 2, indicate your decision by adding
   13.37 + * "[Contributor] elects to include this software in this distribution
   13.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   13.39 + * single choice of license, a recipient has the option to distribute
   13.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   13.41 + * to extend the choice of license to its licensees as provided above.
   13.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   13.43 + * Version 2 license, then the option applies only if the new code is
   13.44 + * made subject to such option by the copyright holder.
   13.45 + */
   13.46 +package org.netbeans.html.boot.fx;
   13.47 +
   13.48 +import java.io.IOException;
   13.49 +import java.io.ObjectInputStream;
   13.50 +import java.io.ObjectOutputStream;
   13.51 +import java.net.InetAddress;
   13.52 +import java.net.Socket;
   13.53 +import java.nio.charset.StandardCharsets;
   13.54 +import java.util.logging.Level;
   13.55 +import java.util.logging.Logger;
   13.56 +import javafx.application.Platform;
   13.57 +import javafx.scene.web.WebEngine;
   13.58 +import javafx.util.Callback;
   13.59 +
   13.60 +/**
   13.61 + *
   13.62 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   13.63 + */
   13.64 +final class FXInspect implements Runnable {
   13.65 +    private static final Logger LOG = Logger.getLogger(FXInspect.class.getName());
   13.66 +    
   13.67 +    
   13.68 +    private final WebEngine engine;
   13.69 +    private final ObjectInputStream input;
   13.70 +    private Dbgr dbg;
   13.71 +    
   13.72 +    private FXInspect(WebEngine engine, int port) throws IOException {
   13.73 +        this.engine = engine;
   13.74 +        
   13.75 +        Socket socket = new Socket(InetAddress.getByName(null), port);
   13.76 +        ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
   13.77 +        this.input = new ObjectInputStream(socket.getInputStream());
   13.78 +        initializeDebugger(output);
   13.79 +    }
   13.80 +    
   13.81 +    static boolean initialize(WebEngine engine) {
   13.82 +        final int inspectPort = Integer.getInteger("netbeans.inspect.port", -1); // NOI18N
   13.83 +        if (inspectPort != -1) {
   13.84 +            try {
   13.85 +                FXInspect inspector = new FXInspect(engine, inspectPort);
   13.86 +                Thread t = new Thread(inspector, "FX<->NetBeans Inspector");
   13.87 +                t.start();
   13.88 +                return true;
   13.89 +            } catch (IOException ex) {
   13.90 +                LOG.log(Level.INFO, "Cannot connect to NetBeans IDE to port " + inspectPort, ex); // NOI18N
   13.91 +            }
   13.92 +        }
   13.93 +        return false;
   13.94 +    }
   13.95 +    
   13.96 +    private void initializeDebugger(final ObjectOutputStream output) {
   13.97 +        Platform.runLater(new Runnable() {
   13.98 +            @Override
   13.99 +            public void run() {
  13.100 +                dbg = new Dbgr(engine, new Callback<String,Void>() {
  13.101 +                    @Override
  13.102 +                    public Void call(String message) {
  13.103 +                        try {
  13.104 +                            byte[] bytes = message.getBytes(StandardCharsets.UTF_8);
  13.105 +                            output.writeInt(bytes.length);
  13.106 +                            output.write(bytes);
  13.107 +                            output.flush();
  13.108 +                        } catch (IOException ioex) {
  13.109 +                            ioex.printStackTrace();
  13.110 +                        }
  13.111 +                        return null;
  13.112 +                    }
  13.113 +                });
  13.114 +            }
  13.115 +        });
  13.116 +    }
  13.117 +
  13.118 +    @Override
  13.119 +    public void run() {
  13.120 +        try {
  13.121 +            while (true) {
  13.122 +                int length = input.readInt();
  13.123 +                byte[] bytes = new byte[length];
  13.124 +                input.readFully(bytes);
  13.125 +                final String message = new String(bytes, StandardCharsets.UTF_8);
  13.126 +                Platform.runLater(new Runnable() {
  13.127 +                    @Override
  13.128 +                    public void run() {
  13.129 +                        dbg.sendMessage(message);
  13.130 +                    }
  13.131 +                });
  13.132 +            }
  13.133 +        } catch (IOException ex) {
  13.134 +            LOG.log(Level.WARNING, null, ex);
  13.135 +        }
  13.136 +    }
  13.137 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXPresenter.java	Tue Jan 07 08:21:57 2014 +0100
    14.3 @@ -0,0 +1,98 @@
    14.4 +/**
    14.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    14.6 + *
    14.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    14.8 + *
    14.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   14.10 + * Other names may be trademarks of their respective owners.
   14.11 + *
   14.12 + * The contents of this file are subject to the terms of either the GNU
   14.13 + * General Public License Version 2 only ("GPL") or the Common
   14.14 + * Development and Distribution License("CDDL") (collectively, the
   14.15 + * "License"). You may not use this file except in compliance with the
   14.16 + * License. You can obtain a copy of the License at
   14.17 + * http://www.netbeans.org/cddl-gplv2.html
   14.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   14.19 + * specific language governing permissions and limitations under the
   14.20 + * License.  When distributing the software, include this License Header
   14.21 + * Notice in each file and include the License file at
   14.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   14.23 + * particular file as subject to the "Classpath" exception as provided
   14.24 + * by Oracle in the GPL Version 2 section of the License file that
   14.25 + * accompanied this code. If applicable, add the following below the
   14.26 + * License Header, with the fields enclosed by brackets [] replaced by
   14.27 + * your own identifying information:
   14.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   14.29 + *
   14.30 + * Contributor(s):
   14.31 + *
   14.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   14.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   14.34 + *
   14.35 + * If you wish your version of this file to be governed by only the CDDL
   14.36 + * or only the GPL Version 2, indicate your decision by adding
   14.37 + * "[Contributor] elects to include this software in this distribution
   14.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   14.39 + * single choice of license, a recipient has the option to distribute
   14.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   14.41 + * to extend the choice of license to its licensees as provided above.
   14.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   14.43 + * Version 2 license, then the option applies only if the new code is
   14.44 + * made subject to such option by the copyright holder.
   14.45 + */
   14.46 +package org.netbeans.html.boot.fx;
   14.47 +
   14.48 +import java.io.BufferedReader;
   14.49 +import java.io.File;
   14.50 +import java.io.Reader;
   14.51 +import java.lang.reflect.Method;
   14.52 +import java.net.URL;
   14.53 +import java.net.URLClassLoader;
   14.54 +import java.util.ArrayList;
   14.55 +import java.util.Arrays;
   14.56 +import java.util.List;
   14.57 +import java.util.logging.Level;
   14.58 +import java.util.logging.Logger;
   14.59 +import javafx.application.Platform;
   14.60 +import javafx.scene.web.WebEngine;
   14.61 +import javafx.scene.web.WebView;
   14.62 +import net.java.html.boot.BrowserBuilder;
   14.63 +import netscape.javascript.JSObject;
   14.64 +import org.apidesign.html.boot.spi.Fn;
   14.65 +import org.openide.util.lookup.ServiceProvider;
   14.66 +
   14.67 +/** This is an implementation class, use {@link BrowserBuilder} API. Just
   14.68 + * include this JAR on classpath and the {@link BrowserBuilder} API will find
   14.69 + * this implementation automatically.
   14.70 + *
   14.71 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   14.72 + */
   14.73 +@ServiceProvider(service = Fn.Presenter.class)
   14.74 +public final class FXPresenter extends AbstractFXPresenter {
   14.75 +    static {
   14.76 +        try {
   14.77 +            try {
   14.78 +                Class<?> c = Class.forName("javafx.application.Platform");
   14.79 +                // OK, on classpath
   14.80 +            } catch (ClassNotFoundException classNotFoundException) {
   14.81 +                Method m = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
   14.82 +                m.setAccessible(true);
   14.83 +                File f = new File(System.getProperty("java.home"), "lib/jfxrt.jar");
   14.84 +                if (f.exists()) {
   14.85 +                    URL l = f.toURI().toURL();
   14.86 +                    m.invoke(ClassLoader.getSystemClassLoader(), l);
   14.87 +                }
   14.88 +            }
   14.89 +        } catch (Exception ex) {
   14.90 +            throw new LinkageError("Can't add jfxrt.jar on the classpath", ex);
   14.91 +        }
   14.92 +    }
   14.93 +
   14.94 +    protected void waitFinished() {
   14.95 +        FXBrwsr.waitFinished();
   14.96 +    }
   14.97 +
   14.98 +    protected WebView findView(final URL resource) {
   14.99 +        return FXBrwsr.findWebView(resource, this);
  14.100 +    }
  14.101 +}
    15.1 --- a/boot-fx/src/test/java/net/java/html/boot/fx/FXBrowsersOnResourceTest.java	Thu Dec 19 17:11:01 2013 +0100
    15.2 +++ b/boot-fx/src/test/java/net/java/html/boot/fx/FXBrowsersOnResourceTest.java	Tue Jan 07 08:21:57 2014 +0100
    15.3 @@ -1,22 +1,44 @@
    15.4  /**
    15.5 - * HTML via Java(tm) Language Bindings
    15.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    15.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    15.8   *
    15.9 - * This program is free software: you can redistribute it and/or modify
   15.10 - * it under the terms of the GNU General Public License as published by
   15.11 - * the Free Software Foundation, version 2 of the License.
   15.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   15.13   *
   15.14 - * This program is distributed in the hope that it will be useful,
   15.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   15.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15.17 - * GNU General Public License for more details. apidesign.org
   15.18 - * designates this particular file as subject to the
   15.19 - * "Classpath" exception as provided by apidesign.org
   15.20 - * in the License file that accompanied this code.
   15.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   15.22 + * Other names may be trademarks of their respective owners.
   15.23   *
   15.24 - * You should have received a copy of the GNU General Public License
   15.25 - * along with this program. Look for COPYING file in the top folder.
   15.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   15.27 + * The contents of this file are subject to the terms of either the GNU
   15.28 + * General Public License Version 2 only ("GPL") or the Common
   15.29 + * Development and Distribution License("CDDL") (collectively, the
   15.30 + * "License"). You may not use this file except in compliance with the
   15.31 + * License. You can obtain a copy of the License at
   15.32 + * http://www.netbeans.org/cddl-gplv2.html
   15.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   15.34 + * specific language governing permissions and limitations under the
   15.35 + * License.  When distributing the software, include this License Header
   15.36 + * Notice in each file and include the License file at
   15.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   15.38 + * particular file as subject to the "Classpath" exception as provided
   15.39 + * by Oracle in the GPL Version 2 section of the License file that
   15.40 + * accompanied this code. If applicable, add the following below the
   15.41 + * License Header, with the fields enclosed by brackets [] replaced by
   15.42 + * your own identifying information:
   15.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   15.44 + *
   15.45 + * Contributor(s):
   15.46 + *
   15.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   15.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   15.49 + *
   15.50 + * If you wish your version of this file to be governed by only the CDDL
   15.51 + * or only the GPL Version 2, indicate your decision by adding
   15.52 + * "[Contributor] elects to include this software in this distribution
   15.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   15.54 + * single choice of license, a recipient has the option to distribute
   15.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   15.56 + * to extend the choice of license to its licensees as provided above.
   15.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   15.58 + * Version 2 license, then the option applies only if the new code is
   15.59 + * made subject to such option by the copyright holder.
   15.60   */
   15.61  package net.java.html.boot.fx;
   15.62  
   15.63 @@ -73,7 +95,7 @@
   15.64              }
   15.65              
   15.66              private void doTest() throws Throwable {
   15.67 -                URL u = FXBrowsersOnResourceTest.class.getResource("/org/apidesign/html/boot/fx/empty.html");
   15.68 +                URL u = FXBrowsersOnResourceTest.class.getResource("/org/netbeans/html/boot/fx/empty.html");
   15.69                  assertNotNull(u, "URL found");
   15.70                  FXBrowsers.load(App.getV1(), u, OnPages.class, "first");
   15.71                  
   15.72 @@ -109,7 +131,7 @@
   15.73              
   15.74              assertEquals(increment(), 1, "Now it is one");
   15.75              
   15.76 -            URL u = FXBrowsersOnResourceTest.class.getResource("/org/apidesign/html/boot/fx/empty.html");
   15.77 +            URL u = FXBrowsersOnResourceTest.class.getResource("/org/netbeans/html/boot/fx/empty.html");
   15.78              assertNotNull(u, "URL found");
   15.79              FXBrowsers.load(App.getV2(), u, OnPages.class, "second", "Hello");
   15.80              
    16.1 --- a/boot-fx/src/test/java/net/java/html/boot/fx/FXBrowsersTest.java	Thu Dec 19 17:11:01 2013 +0100
    16.2 +++ b/boot-fx/src/test/java/net/java/html/boot/fx/FXBrowsersTest.java	Tue Jan 07 08:21:57 2014 +0100
    16.3 @@ -1,22 +1,44 @@
    16.4  /**
    16.5 - * HTML via Java(tm) Language Bindings
    16.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    16.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    16.8   *
    16.9 - * This program is free software: you can redistribute it and/or modify
   16.10 - * it under the terms of the GNU General Public License as published by
   16.11 - * the Free Software Foundation, version 2 of the License.
   16.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   16.13   *
   16.14 - * This program is distributed in the hope that it will be useful,
   16.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   16.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16.17 - * GNU General Public License for more details. apidesign.org
   16.18 - * designates this particular file as subject to the
   16.19 - * "Classpath" exception as provided by apidesign.org
   16.20 - * in the License file that accompanied this code.
   16.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   16.22 + * Other names may be trademarks of their respective owners.
   16.23   *
   16.24 - * You should have received a copy of the GNU General Public License
   16.25 - * along with this program. Look for COPYING file in the top folder.
   16.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   16.27 + * The contents of this file are subject to the terms of either the GNU
   16.28 + * General Public License Version 2 only ("GPL") or the Common
   16.29 + * Development and Distribution License("CDDL") (collectively, the
   16.30 + * "License"). You may not use this file except in compliance with the
   16.31 + * License. You can obtain a copy of the License at
   16.32 + * http://www.netbeans.org/cddl-gplv2.html
   16.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   16.34 + * specific language governing permissions and limitations under the
   16.35 + * License.  When distributing the software, include this License Header
   16.36 + * Notice in each file and include the License file at
   16.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   16.38 + * particular file as subject to the "Classpath" exception as provided
   16.39 + * by Oracle in the GPL Version 2 section of the License file that
   16.40 + * accompanied this code. If applicable, add the following below the
   16.41 + * License Header, with the fields enclosed by brackets [] replaced by
   16.42 + * your own identifying information:
   16.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   16.44 + *
   16.45 + * Contributor(s):
   16.46 + *
   16.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   16.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   16.49 + *
   16.50 + * If you wish your version of this file to be governed by only the CDDL
   16.51 + * or only the GPL Version 2, indicate your decision by adding
   16.52 + * "[Contributor] elects to include this software in this distribution
   16.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   16.54 + * single choice of license, a recipient has the option to distribute
   16.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   16.56 + * to extend the choice of license to its licensees as provided above.
   16.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   16.58 + * Version 2 license, then the option applies only if the new code is
   16.59 + * made subject to such option by the copyright holder.
   16.60   */
   16.61  package net.java.html.boot.fx;
   16.62  
   16.63 @@ -73,7 +95,7 @@
   16.64              }
   16.65              
   16.66              private void doTest() throws Throwable {
   16.67 -                URL u = FXBrowsersTest.class.getResource("/org/apidesign/html/boot/fx/empty.html");
   16.68 +                URL u = FXBrowsersTest.class.getResource("/org/netbeans/html/boot/fx/empty.html");
   16.69                  assertNotNull(u, "URL found");
   16.70                  FXBrowsers.load(App.getV1(), u, OnPages.class, "first");
   16.71                  
   16.72 @@ -108,7 +130,7 @@
   16.73              
   16.74              assertEquals(increment(), 1, "Now it is one");
   16.75              
   16.76 -            URL u = FXBrowsersTest.class.getResource("/org/apidesign/html/boot/fx/empty.html");
   16.77 +            URL u = FXBrowsersTest.class.getResource("/org/netbeans/html/boot/fx/empty.html");
   16.78              assertNotNull(u, "URL found");
   16.79              FXBrowsers.load(App.getV2(), u, OnPages.class, "second", "Hello");
   16.80              
    17.1 --- a/boot-fx/src/test/java/org/apidesign/html/boot/fx/BootstrapTest.java	Thu Dec 19 17:11:01 2013 +0100
    17.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.3 @@ -1,93 +0,0 @@
    17.4 -/**
    17.5 - * HTML via Java(tm) Language Bindings
    17.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    17.7 - *
    17.8 - * This program is free software: you can redistribute it and/or modify
    17.9 - * it under the terms of the GNU General Public License as published by
   17.10 - * the Free Software Foundation, version 2 of the License.
   17.11 - *
   17.12 - * This program is distributed in the hope that it will be useful,
   17.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   17.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17.15 - * GNU General Public License for more details. apidesign.org
   17.16 - * designates this particular file as subject to the
   17.17 - * "Classpath" exception as provided by apidesign.org
   17.18 - * in the License file that accompanied this code.
   17.19 - *
   17.20 - * You should have received a copy of the GNU General Public License
   17.21 - * along with this program. Look for COPYING file in the top folder.
   17.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   17.23 - */
   17.24 -package org.apidesign.html.boot.fx;
   17.25 -
   17.26 -import java.lang.annotation.Annotation;
   17.27 -import java.lang.reflect.Method;
   17.28 -import java.util.ArrayList;
   17.29 -import java.util.List;
   17.30 -import java.util.concurrent.Executors;
   17.31 -import net.java.html.boot.BrowserBuilder;
   17.32 -import org.apidesign.html.boot.impl.FnContext;
   17.33 -import org.apidesign.html.boot.spi.Fn;
   17.34 -import org.apidesign.html.json.tck.JavaScriptTCK;
   17.35 -import org.apidesign.html.json.tck.KOTest;
   17.36 -import org.testng.annotations.Factory;
   17.37 -import org.testng.annotations.Test;
   17.38 -
   17.39 -/**
   17.40 - *
   17.41 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   17.42 - */
   17.43 -public class BootstrapTest {
   17.44 -    private static Class<?> browserClass;
   17.45 -    private static Fn.Presenter browserPresenter;
   17.46 -    
   17.47 -    public BootstrapTest() {
   17.48 -    }
   17.49 -
   17.50 -    @Factory public static Object[] compatibilityTests() throws Exception {
   17.51 -        final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(BootstrapTest.class).
   17.52 -            loadPage("empty.html").
   17.53 -            invoke("initialized");
   17.54 -
   17.55 -        Executors.newSingleThreadExecutor().submit(new Runnable() {
   17.56 -            @Override
   17.57 -            public void run() {
   17.58 -                bb.showAndWait();
   17.59 -            }
   17.60 -        });
   17.61 -
   17.62 -        List<Object> res = new ArrayList<Object>();
   17.63 -        Class<? extends Annotation> test = 
   17.64 -            loadClass().getClassLoader().loadClass(KOTest.class.getName()).
   17.65 -            asSubclass(Annotation.class);
   17.66 -
   17.67 -        Class[] arr = (Class[]) loadClass().getDeclaredMethod("tests").invoke(null);
   17.68 -        for (Class c : arr) {
   17.69 -            for (Method m : c.getMethods()) {
   17.70 -                if (m.getAnnotation(test) != null) {
   17.71 -                    res.add(new KOFx(browserPresenter, m));
   17.72 -                }
   17.73 -            }
   17.74 -        }
   17.75 -        return res.toArray();
   17.76 -    }
   17.77 -
   17.78 -    static synchronized Class<?> loadClass() throws InterruptedException {
   17.79 -        while (browserClass == null) {
   17.80 -            BootstrapTest.class.wait();
   17.81 -        }
   17.82 -        return browserClass;
   17.83 -    }
   17.84 -    
   17.85 -    public static synchronized void ready(Class<?> browserCls) throws Exception {
   17.86 -        browserClass = browserCls;
   17.87 -        browserPresenter = Fn.activePresenter();
   17.88 -        BootstrapTest.class.notifyAll();
   17.89 -    }
   17.90 -    
   17.91 -    public static void initialized() throws Exception {
   17.92 -        Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(BootstrapTest.class.getName());
   17.93 -        Method m = classpathClass.getMethod("ready", Class.class);
   17.94 -        m.invoke(null, FxJavaScriptTst.class);
   17.95 -    }
   17.96 -}
    18.1 --- a/boot-fx/src/test/java/org/apidesign/html/boot/fx/FxJavaScriptTst.java	Thu Dec 19 17:11:01 2013 +0100
    18.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.3 @@ -1,33 +0,0 @@
    18.4 -/**
    18.5 - * HTML via Java(tm) Language Bindings
    18.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    18.7 - *
    18.8 - * This program is free software: you can redistribute it and/or modify
    18.9 - * it under the terms of the GNU General Public License as published by
   18.10 - * the Free Software Foundation, version 2 of the License.
   18.11 - *
   18.12 - * This program is distributed in the hope that it will be useful,
   18.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   18.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18.15 - * GNU General Public License for more details. apidesign.org
   18.16 - * designates this particular file as subject to the
   18.17 - * "Classpath" exception as provided by apidesign.org
   18.18 - * in the License file that accompanied this code.
   18.19 - *
   18.20 - * You should have received a copy of the GNU General Public License
   18.21 - * along with this program. Look for COPYING file in the top folder.
   18.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   18.23 - */
   18.24 -package org.apidesign.html.boot.fx;
   18.25 -
   18.26 -import org.apidesign.html.json.tck.JavaScriptTCK;
   18.27 -
   18.28 -/**
   18.29 - *
   18.30 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   18.31 - */
   18.32 -public final class FxJavaScriptTst extends JavaScriptTCK {
   18.33 -    public static Class[] tests() {
   18.34 -        return testClasses();
   18.35 -    }
   18.36 -}
    19.1 --- a/boot-fx/src/test/java/org/apidesign/html/boot/fx/KOFx.java	Thu Dec 19 17:11:01 2013 +0100
    19.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.3 @@ -1,103 +0,0 @@
    19.4 -/**
    19.5 - * HTML via Java(tm) Language Bindings
    19.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    19.7 - *
    19.8 - * This program is free software: you can redistribute it and/or modify
    19.9 - * it under the terms of the GNU General Public License as published by
   19.10 - * the Free Software Foundation, version 2 of the License.
   19.11 - *
   19.12 - * This program is distributed in the hope that it will be useful,
   19.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   19.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   19.15 - * GNU General Public License for more details. apidesign.org
   19.16 - * designates this particular file as subject to the
   19.17 - * "Classpath" exception as provided by apidesign.org
   19.18 - * in the License file that accompanied this code.
   19.19 - *
   19.20 - * You should have received a copy of the GNU General Public License
   19.21 - * along with this program. Look for COPYING file in the top folder.
   19.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   19.23 - */
   19.24 -package org.apidesign.html.boot.fx;
   19.25 -
   19.26 -import java.lang.reflect.InvocationTargetException;
   19.27 -import java.lang.reflect.Method;
   19.28 -import javafx.application.Platform;
   19.29 -import org.apidesign.html.boot.impl.FnContext;
   19.30 -import org.apidesign.html.boot.spi.Fn;
   19.31 -import org.testng.IHookCallBack;
   19.32 -import org.testng.IHookable;
   19.33 -import org.testng.ITest;
   19.34 -import org.testng.ITestResult;
   19.35 -import org.testng.annotations.Test;
   19.36 -
   19.37 -/**
   19.38 - *
   19.39 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   19.40 - */
   19.41 -public final class KOFx implements ITest, IHookable, Runnable {
   19.42 -    private final Fn.Presenter p;
   19.43 -    private final Method m;
   19.44 -    private Object result;
   19.45 -    private Object inst;
   19.46 -
   19.47 -    KOFx(Fn.Presenter p, Method m) {
   19.48 -        this.p = p;
   19.49 -        this.m = m;
   19.50 -    }
   19.51 -
   19.52 -    @Override
   19.53 -    public String getTestName() {
   19.54 -        return m.getName();
   19.55 -    }
   19.56 -
   19.57 -    @Test
   19.58 -    public synchronized void executeTest() throws Exception {
   19.59 -        if (result == null) {
   19.60 -            Platform.runLater(this);
   19.61 -            wait();
   19.62 -        }
   19.63 -        if (result instanceof Exception) {
   19.64 -            throw (Exception)result;
   19.65 -        }
   19.66 -        if (result instanceof Error) {
   19.67 -            throw (Error)result;
   19.68 -        }
   19.69 -    }
   19.70 -
   19.71 -    @Override
   19.72 -    public synchronized void run() {
   19.73 -        boolean notify = true;
   19.74 -        try {
   19.75 -            FnContext.currentPresenter(p);
   19.76 -            if (inst == null) {
   19.77 -                inst = m.getDeclaringClass().newInstance();
   19.78 -            }
   19.79 -            result = m.invoke(inst);
   19.80 -            if (result == null) {
   19.81 -                result = this;
   19.82 -            }
   19.83 -        } catch (InvocationTargetException ex) {
   19.84 -            Throwable r = ex.getTargetException();
   19.85 -            if (r instanceof InterruptedException) {
   19.86 -                notify = false;
   19.87 -                Platform.runLater(this);
   19.88 -                return;
   19.89 -            }
   19.90 -            result = r;
   19.91 -        } catch (Exception ex) {
   19.92 -            result = ex;
   19.93 -        } finally {
   19.94 -            if (notify) {
   19.95 -                notifyAll();
   19.96 -            }
   19.97 -            FnContext.currentPresenter(null);
   19.98 -        }
   19.99 -    }
  19.100 -
  19.101 -    @Override
  19.102 -    public void run(IHookCallBack ihcb, ITestResult itr) {
  19.103 -        ihcb.runTestMethod(itr);
  19.104 -    }
  19.105 -    
  19.106 -}
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/boot-fx/src/test/java/org/netbeans/html/boot/fx/BootstrapTest.java	Tue Jan 07 08:21:57 2014 +0100
    20.3 @@ -0,0 +1,115 @@
    20.4 +/**
    20.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    20.6 + *
    20.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    20.8 + *
    20.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   20.10 + * Other names may be trademarks of their respective owners.
   20.11 + *
   20.12 + * The contents of this file are subject to the terms of either the GNU
   20.13 + * General Public License Version 2 only ("GPL") or the Common
   20.14 + * Development and Distribution License("CDDL") (collectively, the
   20.15 + * "License"). You may not use this file except in compliance with the
   20.16 + * License. You can obtain a copy of the License at
   20.17 + * http://www.netbeans.org/cddl-gplv2.html
   20.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   20.19 + * specific language governing permissions and limitations under the
   20.20 + * License.  When distributing the software, include this License Header
   20.21 + * Notice in each file and include the License file at
   20.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   20.23 + * particular file as subject to the "Classpath" exception as provided
   20.24 + * by Oracle in the GPL Version 2 section of the License file that
   20.25 + * accompanied this code. If applicable, add the following below the
   20.26 + * License Header, with the fields enclosed by brackets [] replaced by
   20.27 + * your own identifying information:
   20.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   20.29 + *
   20.30 + * Contributor(s):
   20.31 + *
   20.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   20.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   20.34 + *
   20.35 + * If you wish your version of this file to be governed by only the CDDL
   20.36 + * or only the GPL Version 2, indicate your decision by adding
   20.37 + * "[Contributor] elects to include this software in this distribution
   20.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   20.39 + * single choice of license, a recipient has the option to distribute
   20.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   20.41 + * to extend the choice of license to its licensees as provided above.
   20.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   20.43 + * Version 2 license, then the option applies only if the new code is
   20.44 + * made subject to such option by the copyright holder.
   20.45 + */
   20.46 +package org.netbeans.html.boot.fx;
   20.47 +
   20.48 +import java.lang.annotation.Annotation;
   20.49 +import java.lang.reflect.Method;
   20.50 +import java.util.ArrayList;
   20.51 +import java.util.List;
   20.52 +import java.util.concurrent.Executors;
   20.53 +import net.java.html.boot.BrowserBuilder;
   20.54 +import org.netbeans.html.boot.impl.FnContext;
   20.55 +import org.apidesign.html.boot.spi.Fn;
   20.56 +import org.apidesign.html.json.tck.JavaScriptTCK;
   20.57 +import org.apidesign.html.json.tck.KOTest;
   20.58 +import org.testng.annotations.Factory;
   20.59 +import org.testng.annotations.Test;
   20.60 +
   20.61 +/**
   20.62 + *
   20.63 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   20.64 + */
   20.65 +public class BootstrapTest {
   20.66 +    private static Class<?> browserClass;
   20.67 +    private static Fn.Presenter browserPresenter;
   20.68 +    
   20.69 +    public BootstrapTest() {
   20.70 +    }
   20.71 +
   20.72 +    @Factory public static Object[] compatibilityTests() throws Exception {
   20.73 +        final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(BootstrapTest.class).
   20.74 +            loadPage("empty.html").
   20.75 +            invoke("initialized");
   20.76 +
   20.77 +        Executors.newSingleThreadExecutor().submit(new Runnable() {
   20.78 +            @Override
   20.79 +            public void run() {
   20.80 +                bb.showAndWait();
   20.81 +            }
   20.82 +        });
   20.83 +
   20.84 +        List<Object> res = new ArrayList<Object>();
   20.85 +        Class<? extends Annotation> test = 
   20.86 +            loadClass().getClassLoader().loadClass(KOTest.class.getName()).
   20.87 +            asSubclass(Annotation.class);
   20.88 +
   20.89 +        Class[] arr = (Class[]) loadClass().getDeclaredMethod("tests").invoke(null);
   20.90 +        for (Class c : arr) {
   20.91 +            for (Method m : c.getMethods()) {
   20.92 +                if (m.getAnnotation(test) != null) {
   20.93 +                    res.add(new KOFx(browserPresenter, m));
   20.94 +                }
   20.95 +            }
   20.96 +        }
   20.97 +        return res.toArray();
   20.98 +    }
   20.99 +
  20.100 +    static synchronized Class<?> loadClass() throws InterruptedException {
  20.101 +        while (browserClass == null) {
  20.102 +            BootstrapTest.class.wait();
  20.103 +        }
  20.104 +        return browserClass;
  20.105 +    }
  20.106 +    
  20.107 +    public static synchronized void ready(Class<?> browserCls) throws Exception {
  20.108 +        browserClass = browserCls;
  20.109 +        browserPresenter = Fn.activePresenter();
  20.110 +        BootstrapTest.class.notifyAll();
  20.111 +    }
  20.112 +    
  20.113 +    public static void initialized() throws Exception {
  20.114 +        Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(BootstrapTest.class.getName());
  20.115 +        Method m = classpathClass.getMethod("ready", Class.class);
  20.116 +        m.invoke(null, FxJavaScriptTst.class);
  20.117 +    }
  20.118 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/boot-fx/src/test/java/org/netbeans/html/boot/fx/FXPresenterTst.java	Tue Jan 07 08:21:57 2014 +0100
    21.3 @@ -0,0 +1,71 @@
    21.4 +/**
    21.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    21.6 + *
    21.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    21.8 + *
    21.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   21.10 + * Other names may be trademarks of their respective owners.
   21.11 + *
   21.12 + * The contents of this file are subject to the terms of either the GNU
   21.13 + * General Public License Version 2 only ("GPL") or the Common
   21.14 + * Development and Distribution License("CDDL") (collectively, the
   21.15 + * "License"). You may not use this file except in compliance with the
   21.16 + * License. You can obtain a copy of the License at
   21.17 + * http://www.netbeans.org/cddl-gplv2.html
   21.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   21.19 + * specific language governing permissions and limitations under the
   21.20 + * License.  When distributing the software, include this License Header
   21.21 + * Notice in each file and include the License file at
   21.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   21.23 + * particular file as subject to the "Classpath" exception as provided
   21.24 + * by Oracle in the GPL Version 2 section of the License file that
   21.25 + * accompanied this code. If applicable, add the following below the
   21.26 + * License Header, with the fields enclosed by brackets [] replaced by
   21.27 + * your own identifying information:
   21.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   21.29 + *
   21.30 + * Contributor(s):
   21.31 + *
   21.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   21.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   21.34 + *
   21.35 + * If you wish your version of this file to be governed by only the CDDL
   21.36 + * or only the GPL Version 2, indicate your decision by adding
   21.37 + * "[Contributor] elects to include this software in this distribution
   21.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   21.39 + * single choice of license, a recipient has the option to distribute
   21.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   21.41 + * to extend the choice of license to its licensees as provided above.
   21.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   21.43 + * Version 2 license, then the option applies only if the new code is
   21.44 + * made subject to such option by the copyright holder.
   21.45 + */
   21.46 +package org.netbeans.html.boot.fx;
   21.47 +
   21.48 +import net.java.html.js.JavaScriptBody;
   21.49 +import static org.testng.Assert.*;
   21.50 +import org.testng.annotations.Test;
   21.51 +
   21.52 +/**
   21.53 + *
   21.54 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   21.55 + */
   21.56 +public class FXPresenterTst {
   21.57 +    @Test public void showClassLoader() {
   21.58 +        R run = new R();
   21.59 +        callback(run);
   21.60 +        assertEquals(run.cnt, 1, "Can call even private implementation classes");
   21.61 +    }
   21.62 +    
   21.63 +    @JavaScriptBody(args = { "r" }, javacall = true, body = "r.@java.lang.Runnable::run()();")
   21.64 +    private static native void callback(Runnable r);
   21.65 +
   21.66 +    private static class R implements Runnable {
   21.67 +        int cnt;
   21.68 +
   21.69 +        @Override
   21.70 +        public void run() {
   21.71 +            cnt++;
   21.72 +        }
   21.73 +    }
   21.74 +}
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/boot-fx/src/test/java/org/netbeans/html/boot/fx/FxJavaScriptTst.java	Tue Jan 07 08:21:57 2014 +0100
    22.3 @@ -0,0 +1,55 @@
    22.4 +/**
    22.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    22.6 + *
    22.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    22.8 + *
    22.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   22.10 + * Other names may be trademarks of their respective owners.
   22.11 + *
   22.12 + * The contents of this file are subject to the terms of either the GNU
   22.13 + * General Public License Version 2 only ("GPL") or the Common
   22.14 + * Development and Distribution License("CDDL") (collectively, the
   22.15 + * "License"). You may not use this file except in compliance with the
   22.16 + * License. You can obtain a copy of the License at
   22.17 + * http://www.netbeans.org/cddl-gplv2.html
   22.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   22.19 + * specific language governing permissions and limitations under the
   22.20 + * License.  When distributing the software, include this License Header
   22.21 + * Notice in each file and include the License file at
   22.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   22.23 + * particular file as subject to the "Classpath" exception as provided
   22.24 + * by Oracle in the GPL Version 2 section of the License file that
   22.25 + * accompanied this code. If applicable, add the following below the
   22.26 + * License Header, with the fields enclosed by brackets [] replaced by
   22.27 + * your own identifying information:
   22.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   22.29 + *
   22.30 + * Contributor(s):
   22.31 + *
   22.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   22.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   22.34 + *
   22.35 + * If you wish your version of this file to be governed by only the CDDL
   22.36 + * or only the GPL Version 2, indicate your decision by adding
   22.37 + * "[Contributor] elects to include this software in this distribution
   22.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   22.39 + * single choice of license, a recipient has the option to distribute
   22.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   22.41 + * to extend the choice of license to its licensees as provided above.
   22.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   22.43 + * Version 2 license, then the option applies only if the new code is
   22.44 + * made subject to such option by the copyright holder.
   22.45 + */
   22.46 +package org.netbeans.html.boot.fx;
   22.47 +
   22.48 +import org.apidesign.html.json.tck.JavaScriptTCK;
   22.49 +
   22.50 +/**
   22.51 + *
   22.52 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   22.53 + */
   22.54 +public final class FxJavaScriptTst extends JavaScriptTCK {
   22.55 +    public static Class[] tests() {
   22.56 +        return testClasses();
   22.57 +    }
   22.58 +}
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/boot-fx/src/test/java/org/netbeans/html/boot/fx/KOFx.java	Tue Jan 07 08:21:57 2014 +0100
    23.3 @@ -0,0 +1,125 @@
    23.4 +/**
    23.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    23.6 + *
    23.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    23.8 + *
    23.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   23.10 + * Other names may be trademarks of their respective owners.
   23.11 + *
   23.12 + * The contents of this file are subject to the terms of either the GNU
   23.13 + * General Public License Version 2 only ("GPL") or the Common
   23.14 + * Development and Distribution License("CDDL") (collectively, the
   23.15 + * "License"). You may not use this file except in compliance with the
   23.16 + * License. You can obtain a copy of the License at
   23.17 + * http://www.netbeans.org/cddl-gplv2.html
   23.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   23.19 + * specific language governing permissions and limitations under the
   23.20 + * License.  When distributing the software, include this License Header
   23.21 + * Notice in each file and include the License file at
   23.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   23.23 + * particular file as subject to the "Classpath" exception as provided
   23.24 + * by Oracle in the GPL Version 2 section of the License file that
   23.25 + * accompanied this code. If applicable, add the following below the
   23.26 + * License Header, with the fields enclosed by brackets [] replaced by
   23.27 + * your own identifying information:
   23.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   23.29 + *
   23.30 + * Contributor(s):
   23.31 + *
   23.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   23.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   23.34 + *
   23.35 + * If you wish your version of this file to be governed by only the CDDL
   23.36 + * or only the GPL Version 2, indicate your decision by adding
   23.37 + * "[Contributor] elects to include this software in this distribution
   23.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   23.39 + * single choice of license, a recipient has the option to distribute
   23.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   23.41 + * to extend the choice of license to its licensees as provided above.
   23.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   23.43 + * Version 2 license, then the option applies only if the new code is
   23.44 + * made subject to such option by the copyright holder.
   23.45 + */
   23.46 +package org.netbeans.html.boot.fx;
   23.47 +
   23.48 +import java.lang.reflect.InvocationTargetException;
   23.49 +import java.lang.reflect.Method;
   23.50 +import javafx.application.Platform;
   23.51 +import org.netbeans.html.boot.impl.FnContext;
   23.52 +import org.apidesign.html.boot.spi.Fn;
   23.53 +import org.testng.IHookCallBack;
   23.54 +import org.testng.IHookable;
   23.55 +import org.testng.ITest;
   23.56 +import org.testng.ITestResult;
   23.57 +import org.testng.annotations.Test;
   23.58 +
   23.59 +/**
   23.60 + *
   23.61 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   23.62 + */
   23.63 +public final class KOFx implements ITest, IHookable, Runnable {
   23.64 +    private final Fn.Presenter p;
   23.65 +    private final Method m;
   23.66 +    private Object result;
   23.67 +    private Object inst;
   23.68 +
   23.69 +    KOFx(Fn.Presenter p, Method m) {
   23.70 +        this.p = p;
   23.71 +        this.m = m;
   23.72 +    }
   23.73 +
   23.74 +    @Override
   23.75 +    public String getTestName() {
   23.76 +        return m.getName();
   23.77 +    }
   23.78 +
   23.79 +    @Test
   23.80 +    public synchronized void executeTest() throws Exception {
   23.81 +        if (result == null) {
   23.82 +            Platform.runLater(this);
   23.83 +            wait();
   23.84 +        }
   23.85 +        if (result instanceof Exception) {
   23.86 +            throw (Exception)result;
   23.87 +        }
   23.88 +        if (result instanceof Error) {
   23.89 +            throw (Error)result;
   23.90 +        }
   23.91 +    }
   23.92 +
   23.93 +    @Override
   23.94 +    public synchronized void run() {
   23.95 +        boolean notify = true;
   23.96 +        try {
   23.97 +            FnContext.currentPresenter(p);
   23.98 +            if (inst == null) {
   23.99 +                inst = m.getDeclaringClass().newInstance();
  23.100 +            }
  23.101 +            result = m.invoke(inst);
  23.102 +            if (result == null) {
  23.103 +                result = this;
  23.104 +            }
  23.105 +        } catch (InvocationTargetException ex) {
  23.106 +            Throwable r = ex.getTargetException();
  23.107 +            if (r instanceof InterruptedException) {
  23.108 +                notify = false;
  23.109 +                Platform.runLater(this);
  23.110 +                return;
  23.111 +            }
  23.112 +            result = r;
  23.113 +        } catch (Exception ex) {
  23.114 +            result = ex;
  23.115 +        } finally {
  23.116 +            if (notify) {
  23.117 +                notifyAll();
  23.118 +            }
  23.119 +            FnContext.currentPresenter(null);
  23.120 +        }
  23.121 +    }
  23.122 +
  23.123 +    @Override
  23.124 +    public void run(IHookCallBack ihcb, ITestResult itr) {
  23.125 +        ihcb.runTestMethod(itr);
  23.126 +    }
  23.127 +    
  23.128 +}
    24.1 --- a/boot-fx/src/test/resources/net/java/html/boot/fx/wnd.js	Thu Dec 19 17:11:01 2013 +0100
    24.2 +++ b/boot-fx/src/test/resources/net/java/html/boot/fx/wnd.js	Tue Jan 07 08:21:57 2014 +0100
    24.3 @@ -1,22 +1,44 @@
    24.4  /*
    24.5 - * HTML via Java(tm) Language Bindings
    24.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    24.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    24.8   *
    24.9 - * This program is free software: you can redistribute it and/or modify
   24.10 - * it under the terms of the GNU General Public License as published by
   24.11 - * the Free Software Foundation, version 2 of the License.
   24.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   24.13   *
   24.14 - * This program is distributed in the hope that it will be useful,
   24.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   24.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   24.17 - * GNU General Public License for more details. apidesign.org
   24.18 - * designates this particular file as subject to the
   24.19 - * "Classpath" exception as provided by apidesign.org
   24.20 - * in the License file that accompanied this code.
   24.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   24.22 + * Other names may be trademarks of their respective owners.
   24.23   *
   24.24 - * You should have received a copy of the GNU General Public License
   24.25 - * along with this program. Look for COPYING file in the top folder.
   24.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   24.27 + * The contents of this file are subject to the terms of either the GNU
   24.28 + * General Public License Version 2 only ("GPL") or the Common
   24.29 + * Development and Distribution License("CDDL") (collectively, the
   24.30 + * "License"). You may not use this file except in compliance with the
   24.31 + * License. You can obtain a copy of the License at
   24.32 + * http://www.netbeans.org/cddl-gplv2.html
   24.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   24.34 + * specific language governing permissions and limitations under the
   24.35 + * License.  When distributing the software, include this License Header
   24.36 + * Notice in each file and include the License file at
   24.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   24.38 + * particular file as subject to the "Classpath" exception as provided
   24.39 + * by Oracle in the GPL Version 2 section of the License file that
   24.40 + * accompanied this code. If applicable, add the following below the
   24.41 + * License Header, with the fields enclosed by brackets [] replaced by
   24.42 + * your own identifying information:
   24.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   24.44 + *
   24.45 + * Contributor(s):
   24.46 + *
   24.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   24.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   24.49 + *
   24.50 + * If you wish your version of this file to be governed by only the CDDL
   24.51 + * or only the GPL Version 2, indicate your decision by adding
   24.52 + * "[Contributor] elects to include this software in this distribution
   24.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   24.54 + * single choice of license, a recipient has the option to distribute
   24.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   24.56 + * to extend the choice of license to its licensees as provided above.
   24.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   24.58 + * Version 2 license, then the option applies only if the new code is
   24.59 + * made subject to such option by the copyright holder.
   24.60   */
   24.61  if (typeof wnd !== 'undefined') {
   24.62      throw 'Window should not be defined yet: ' + wnd;
    25.1 --- a/boot-fx/src/test/resources/org/apidesign/html/boot/fx/empty.html	Thu Dec 19 17:11:01 2013 +0100
    25.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.3 @@ -1,33 +0,0 @@
    25.4 -<!--
    25.5 -
    25.6 -    HTML via Java(tm) Language Bindings
    25.7 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    25.8 -
    25.9 -    This program is free software: you can redistribute it and/or modify
   25.10 -    it under the terms of the GNU General Public License as published by
   25.11 -    the Free Software Foundation, version 2 of the License.
   25.12 -
   25.13 -    This program is distributed in the hope that it will be useful,
   25.14 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   25.15 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   25.16 -    GNU General Public License for more details. apidesign.org
   25.17 -    designates this particular file as subject to the
   25.18 -    "Classpath" exception as provided by apidesign.org
   25.19 -    in the License file that accompanied this code.
   25.20 -
   25.21 -    You should have received a copy of the GNU General Public License
   25.22 -    along with this program. Look for COPYING file in the top folder.
   25.23 -    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   25.24 -
   25.25 --->
   25.26 -<!DOCTYPE html>
   25.27 -<html>
   25.28 -    <head>
   25.29 -        <title>FX Presenter Harness</title>
   25.30 -        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   25.31 -        <meta name="viewport" content="width=device-width">
   25.32 -    </head>
   25.33 -    <body>
   25.34 -        <div>FX Presenter Harness</div>
   25.35 -    </body>
   25.36 -</html>
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/boot-fx/src/test/resources/org/netbeans/html/boot/fx/empty.html	Tue Jan 07 08:21:57 2014 +0100
    26.3 @@ -0,0 +1,55 @@
    26.4 +<!--
    26.5 +
    26.6 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    26.7 +
    26.8 +    Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    26.9 +
   26.10 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   26.11 +    Other names may be trademarks of their respective owners.
   26.12 +
   26.13 +    The contents of this file are subject to the terms of either the GNU
   26.14 +    General Public License Version 2 only ("GPL") or the Common
   26.15 +    Development and Distribution License("CDDL") (collectively, the
   26.16 +    "License"). You may not use this file except in compliance with the
   26.17 +    License. You can obtain a copy of the License at
   26.18 +    http://www.netbeans.org/cddl-gplv2.html
   26.19 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   26.20 +    specific language governing permissions and limitations under the
   26.21 +    License.  When distributing the software, include this License Header
   26.22 +    Notice in each file and include the License file at
   26.23 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   26.24 +    particular file as subject to the "Classpath" exception as provided
   26.25 +    by Oracle in the GPL Version 2 section of the License file that
   26.26 +    accompanied this code. If applicable, add the following below the
   26.27 +    License Header, with the fields enclosed by brackets [] replaced by
   26.28 +    your own identifying information:
   26.29 +    "Portions Copyrighted [year] [name of copyright owner]"
   26.30 +
   26.31 +    Contributor(s):
   26.32 +
   26.33 +    The Original Software is NetBeans. The Initial Developer of the Original
   26.34 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   26.35 +
   26.36 +    If you wish your version of this file to be governed by only the CDDL
   26.37 +    or only the GPL Version 2, indicate your decision by adding
   26.38 +    "[Contributor] elects to include this software in this distribution
   26.39 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
   26.40 +    single choice of license, a recipient has the option to distribute
   26.41 +    your version of this file under either the CDDL, the GPL Version 2 or
   26.42 +    to extend the choice of license to its licensees as provided above.
   26.43 +    However, if you add GPL Version 2 code and therefore, elected the GPL
   26.44 +    Version 2 license, then the option applies only if the new code is
   26.45 +    made subject to such option by the copyright holder.
   26.46 +
   26.47 +-->
   26.48 +<!DOCTYPE html>
   26.49 +<html>
   26.50 +    <head>
   26.51 +        <title>FX Presenter Harness</title>
   26.52 +        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   26.53 +        <meta name="viewport" content="width=device-width">
   26.54 +    </head>
   26.55 +    <body>
   26.56 +        <div>FX Presenter Harness</div>
   26.57 +    </body>
   26.58 +</html>
    27.1 --- a/boot/pom.xml	Thu Dec 19 17:11:01 2013 +0100
    27.2 +++ b/boot/pom.xml	Tue Jan 07 08:21:57 2014 +0100
    27.3 @@ -2,11 +2,11 @@
    27.4  <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">
    27.5    <modelVersion>4.0.0</modelVersion>
    27.6    <parent>
    27.7 -    <groupId>org.apidesign</groupId>
    27.8 -    <artifactId>html</artifactId>
    27.9 +    <groupId>org.netbeans.html</groupId>
   27.10 +    <artifactId>pom</artifactId>
   27.11      <version>0.7-SNAPSHOT</version>
   27.12    </parent>
   27.13 -  <groupId>org.apidesign.html</groupId>
   27.14 +  <groupId>org.netbeans.html</groupId>
   27.15    <artifactId>net.java.html.boot</artifactId>
   27.16    <version>0.7-SNAPSHOT</version>
   27.17    <packaging>bundle</packaging>
   27.18 @@ -23,7 +23,8 @@
   27.19                <artifactId>maven-bundle-plugin</artifactId>
   27.20                <configuration>
   27.21                    <instructions>
   27.22 -                      <Agent-Class>org.apidesign.html.boot.impl.JsAgent</Agent-Class>
   27.23 +                      <Agent-Class>org.netbeans.html.boot.impl.JsAgent</Agent-Class>
   27.24 +                      <Eclipse-BuddyPolicy>dependent</Eclipse-BuddyPolicy>
   27.25                    </instructions>
   27.26                </configuration>
   27.27            </plugin>
    28.1 --- a/boot/src/main/java/net/java/html/boot/BrowserBuilder.java	Thu Dec 19 17:11:01 2013 +0100
    28.2 +++ b/boot/src/main/java/net/java/html/boot/BrowserBuilder.java	Tue Jan 07 08:21:57 2014 +0100
    28.3 @@ -1,22 +1,44 @@
    28.4  /**
    28.5 - * HTML via Java(tm) Language Bindings
    28.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    28.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    28.8   *
    28.9 - * This program is free software: you can redistribute it and/or modify
   28.10 - * it under the terms of the GNU General Public License as published by
   28.11 - * the Free Software Foundation, version 2 of the License.
   28.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   28.13   *
   28.14 - * This program is distributed in the hope that it will be useful,
   28.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   28.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   28.17 - * GNU General Public License for more details. apidesign.org
   28.18 - * designates this particular file as subject to the
   28.19 - * "Classpath" exception as provided by apidesign.org
   28.20 - * in the License file that accompanied this code.
   28.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   28.22 + * Other names may be trademarks of their respective owners.
   28.23   *
   28.24 - * You should have received a copy of the GNU General Public License
   28.25 - * along with this program. Look for COPYING file in the top folder.
   28.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   28.27 + * The contents of this file are subject to the terms of either the GNU
   28.28 + * General Public License Version 2 only ("GPL") or the Common
   28.29 + * Development and Distribution License("CDDL") (collectively, the
   28.30 + * "License"). You may not use this file except in compliance with the
   28.31 + * License. You can obtain a copy of the License at
   28.32 + * http://www.netbeans.org/cddl-gplv2.html
   28.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   28.34 + * specific language governing permissions and limitations under the
   28.35 + * License.  When distributing the software, include this License Header
   28.36 + * Notice in each file and include the License file at
   28.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   28.38 + * particular file as subject to the "Classpath" exception as provided
   28.39 + * by Oracle in the GPL Version 2 section of the License file that
   28.40 + * accompanied this code. If applicable, add the following below the
   28.41 + * License Header, with the fields enclosed by brackets [] replaced by
   28.42 + * your own identifying information:
   28.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   28.44 + *
   28.45 + * Contributor(s):
   28.46 + *
   28.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   28.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   28.49 + *
   28.50 + * If you wish your version of this file to be governed by only the CDDL
   28.51 + * or only the GPL Version 2, indicate your decision by adding
   28.52 + * "[Contributor] elects to include this software in this distribution
   28.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   28.54 + * single choice of license, a recipient has the option to distribute
   28.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   28.56 + * to extend the choice of license to its licensees as provided above.
   28.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   28.58 + * Version 2 license, then the option applies only if the new code is
   28.59 + * made subject to such option by the copyright holder.
   28.60   */
   28.61  package net.java.html.boot;
   28.62  
   28.63 @@ -32,10 +54,10 @@
   28.64  import java.util.logging.Level;
   28.65  import java.util.logging.Logger;
   28.66  import net.java.html.js.JavaScriptBody;
   28.67 -import org.apidesign.html.boot.impl.FnUtils;
   28.68 +import org.netbeans.html.boot.impl.FnUtils;
   28.69  import org.apidesign.html.boot.spi.Fn;
   28.70 -import org.apidesign.html.boot.impl.FindResources;
   28.71 -import org.apidesign.html.boot.impl.FnContext;
   28.72 +import org.netbeans.html.boot.impl.FindResources;
   28.73 +import org.netbeans.html.boot.impl.FnContext;
   28.74  
   28.75  /** Use this builder to launch your Java/HTML based application. Typical
   28.76   * usage in a main method of your application looks like this: 
   28.77 @@ -60,8 +82,8 @@
   28.78   * also needs an implementation on the classpath of one's application. For example
   28.79   * use: <pre>
   28.80   * &lt;dependency&gt;
   28.81 - *   &lt;groupId&gt;org.apidesign.html&lt;/groupId&gt;
   28.82 - *   &lt;artifactId&gt;boot-fx&lt;/artifactId&gt;
   28.83 + *   &lt;groupId&gt;org.netbeans.html&lt;/groupId&gt;
   28.84 + *   &lt;artifactId&gt;net.java.html.boot.fx&lt;/artifactId&gt;
   28.85   *   &lt;scope&gt;runtime&lt;/scope&gt;
   28.86   * &lt;/dependency&gt;
   28.87   * </pre>
    29.1 --- a/boot/src/main/java/net/java/html/boot/package.html	Thu Dec 19 17:11:01 2013 +0100
    29.2 +++ b/boot/src/main/java/net/java/html/boot/package.html	Tue Jan 07 08:21:57 2014 +0100
    29.3 @@ -1,23 +1,45 @@
    29.4  <!--
    29.5  
    29.6 -    HTML via Java(tm) Language Bindings
    29.7 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    29.8 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    29.9  
   29.10 -    This program is free software: you can redistribute it and/or modify
   29.11 -    it under the terms of the GNU General Public License as published by
   29.12 -    the Free Software Foundation, version 2 of the License.
   29.13 +    Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   29.14  
   29.15 -    This program is distributed in the hope that it will be useful,
   29.16 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   29.17 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   29.18 -    GNU General Public License for more details. apidesign.org
   29.19 -    designates this particular file as subject to the
   29.20 -    "Classpath" exception as provided by apidesign.org
   29.21 -    in the License file that accompanied this code.
   29.22 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   29.23 +    Other names may be trademarks of their respective owners.
   29.24  
   29.25 -    You should have received a copy of the GNU General Public License
   29.26 -    along with this program. Look for COPYING file in the top folder.
   29.27 -    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   29.28 +    The contents of this file are subject to the terms of either the GNU
   29.29 +    General Public License Version 2 only ("GPL") or the Common
   29.30 +    Development and Distribution License("CDDL") (collectively, the
   29.31 +    "License"). You may not use this file except in compliance with the
   29.32 +    License. You can obtain a copy of the License at
   29.33 +    http://www.netbeans.org/cddl-gplv2.html
   29.34 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   29.35 +    specific language governing permissions and limitations under the
   29.36 +    License.  When distributing the software, include this License Header
   29.37 +    Notice in each file and include the License file at
   29.38 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   29.39 +    particular file as subject to the "Classpath" exception as provided
   29.40 +    by Oracle in the GPL Version 2 section of the License file that
   29.41 +    accompanied this code. If applicable, add the following below the
   29.42 +    License Header, with the fields enclosed by brackets [] replaced by
   29.43 +    your own identifying information:
   29.44 +    "Portions Copyrighted [year] [name of copyright owner]"
   29.45 +
   29.46 +    Contributor(s):
   29.47 +
   29.48 +    The Original Software is NetBeans. The Initial Developer of the Original
   29.49 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   29.50 +
   29.51 +    If you wish your version of this file to be governed by only the CDDL
   29.52 +    or only the GPL Version 2, indicate your decision by adding
   29.53 +    "[Contributor] elects to include this software in this distribution
   29.54 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
   29.55 +    single choice of license, a recipient has the option to distribute
   29.56 +    your version of this file under either the CDDL, the GPL Version 2 or
   29.57 +    to extend the choice of license to its licensees as provided above.
   29.58 +    However, if you add GPL Version 2 code and therefore, elected the GPL
   29.59 +    Version 2 license, then the option applies only if the new code is
   29.60 +    made subject to such option by the copyright holder.
   29.61  
   29.62  -->
   29.63  <!DOCTYPE html>
    30.1 --- a/boot/src/main/java/net/java/html/js/JavaScriptBody.java	Thu Dec 19 17:11:01 2013 +0100
    30.2 +++ b/boot/src/main/java/net/java/html/js/JavaScriptBody.java	Tue Jan 07 08:21:57 2014 +0100
    30.3 @@ -1,22 +1,44 @@
    30.4  /**
    30.5 - * HTML via Java(tm) Language Bindings
    30.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    30.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    30.8   *
    30.9 - * This program is free software: you can redistribute it and/or modify
   30.10 - * it under the terms of the GNU General Public License as published by
   30.11 - * the Free Software Foundation, version 2 of the License.
   30.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   30.13   *
   30.14 - * This program is distributed in the hope that it will be useful,
   30.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   30.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   30.17 - * GNU General Public License for more details. apidesign.org
   30.18 - * designates this particular file as subject to the
   30.19 - * "Classpath" exception as provided by apidesign.org
   30.20 - * in the License file that accompanied this code.
   30.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   30.22 + * Other names may be trademarks of their respective owners.
   30.23   *
   30.24 - * You should have received a copy of the GNU General Public License
   30.25 - * along with this program. Look for COPYING file in the top folder.
   30.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   30.27 + * The contents of this file are subject to the terms of either the GNU
   30.28 + * General Public License Version 2 only ("GPL") or the Common
   30.29 + * Development and Distribution License("CDDL") (collectively, the
   30.30 + * "License"). You may not use this file except in compliance with the
   30.31 + * License. You can obtain a copy of the License at
   30.32 + * http://www.netbeans.org/cddl-gplv2.html
   30.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   30.34 + * specific language governing permissions and limitations under the
   30.35 + * License.  When distributing the software, include this License Header
   30.36 + * Notice in each file and include the License file at
   30.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   30.38 + * particular file as subject to the "Classpath" exception as provided
   30.39 + * by Oracle in the GPL Version 2 section of the License file that
   30.40 + * accompanied this code. If applicable, add the following below the
   30.41 + * License Header, with the fields enclosed by brackets [] replaced by
   30.42 + * your own identifying information:
   30.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   30.44 + *
   30.45 + * Contributor(s):
   30.46 + *
   30.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   30.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   30.49 + *
   30.50 + * If you wish your version of this file to be governed by only the CDDL
   30.51 + * or only the GPL Version 2, indicate your decision by adding
   30.52 + * "[Contributor] elects to include this software in this distribution
   30.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   30.54 + * single choice of license, a recipient has the option to distribute
   30.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   30.56 + * to extend the choice of license to its licensees as provided above.
   30.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   30.58 + * Version 2 license, then the option applies only if the new code is
   30.59 + * made subject to such option by the copyright holder.
   30.60   */
   30.61  package net.java.html.js;
   30.62  
    31.1 --- a/boot/src/main/java/net/java/html/js/JavaScriptResource.java	Thu Dec 19 17:11:01 2013 +0100
    31.2 +++ b/boot/src/main/java/net/java/html/js/JavaScriptResource.java	Tue Jan 07 08:21:57 2014 +0100
    31.3 @@ -1,22 +1,44 @@
    31.4  /**
    31.5 - * HTML via Java(tm) Language Bindings
    31.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    31.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    31.8   *
    31.9 - * This program is free software: you can redistribute it and/or modify
   31.10 - * it under the terms of the GNU General Public License as published by
   31.11 - * the Free Software Foundation, version 2 of the License.
   31.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   31.13   *
   31.14 - * This program is distributed in the hope that it will be useful,
   31.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   31.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   31.17 - * GNU General Public License for more details. apidesign.org
   31.18 - * designates this particular file as subject to the
   31.19 - * "Classpath" exception as provided by apidesign.org
   31.20 - * in the License file that accompanied this code.
   31.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   31.22 + * Other names may be trademarks of their respective owners.
   31.23   *
   31.24 - * You should have received a copy of the GNU General Public License
   31.25 - * along with this program. Look for COPYING file in the top folder.
   31.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   31.27 + * The contents of this file are subject to the terms of either the GNU
   31.28 + * General Public License Version 2 only ("GPL") or the Common
   31.29 + * Development and Distribution License("CDDL") (collectively, the
   31.30 + * "License"). You may not use this file except in compliance with the
   31.31 + * License. You can obtain a copy of the License at
   31.32 + * http://www.netbeans.org/cddl-gplv2.html
   31.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   31.34 + * specific language governing permissions and limitations under the
   31.35 + * License.  When distributing the software, include this License Header
   31.36 + * Notice in each file and include the License file at
   31.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   31.38 + * particular file as subject to the "Classpath" exception as provided
   31.39 + * by Oracle in the GPL Version 2 section of the License file that
   31.40 + * accompanied this code. If applicable, add the following below the
   31.41 + * License Header, with the fields enclosed by brackets [] replaced by
   31.42 + * your own identifying information:
   31.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   31.44 + *
   31.45 + * Contributor(s):
   31.46 + *
   31.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   31.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   31.49 + *
   31.50 + * If you wish your version of this file to be governed by only the CDDL
   31.51 + * or only the GPL Version 2, indicate your decision by adding
   31.52 + * "[Contributor] elects to include this software in this distribution
   31.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   31.54 + * single choice of license, a recipient has the option to distribute
   31.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   31.56 + * to extend the choice of license to its licensees as provided above.
   31.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   31.58 + * Version 2 license, then the option applies only if the new code is
   31.59 + * made subject to such option by the copyright holder.
   31.60   */
   31.61  package net.java.html.js;
   31.62  
    32.1 --- a/boot/src/main/java/net/java/html/js/package.html	Thu Dec 19 17:11:01 2013 +0100
    32.2 +++ b/boot/src/main/java/net/java/html/js/package.html	Tue Jan 07 08:21:57 2014 +0100
    32.3 @@ -1,23 +1,45 @@
    32.4  <!--
    32.5  
    32.6 -    HTML via Java(tm) Language Bindings
    32.7 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    32.8 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    32.9  
   32.10 -    This program is free software: you can redistribute it and/or modify
   32.11 -    it under the terms of the GNU General Public License as published by
   32.12 -    the Free Software Foundation, version 2 of the License.
   32.13 +    Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   32.14  
   32.15 -    This program is distributed in the hope that it will be useful,
   32.16 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   32.17 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   32.18 -    GNU General Public License for more details. apidesign.org
   32.19 -    designates this particular file as subject to the
   32.20 -    "Classpath" exception as provided by apidesign.org
   32.21 -    in the License file that accompanied this code.
   32.22 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   32.23 +    Other names may be trademarks of their respective owners.
   32.24  
   32.25 -    You should have received a copy of the GNU General Public License
   32.26 -    along with this program. Look for COPYING file in the top folder.
   32.27 -    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   32.28 +    The contents of this file are subject to the terms of either the GNU
   32.29 +    General Public License Version 2 only ("GPL") or the Common
   32.30 +    Development and Distribution License("CDDL") (collectively, the
   32.31 +    "License"). You may not use this file except in compliance with the
   32.32 +    License. You can obtain a copy of the License at
   32.33 +    http://www.netbeans.org/cddl-gplv2.html
   32.34 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   32.35 +    specific language governing permissions and limitations under the
   32.36 +    License.  When distributing the software, include this License Header
   32.37 +    Notice in each file and include the License file at
   32.38 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   32.39 +    particular file as subject to the "Classpath" exception as provided
   32.40 +    by Oracle in the GPL Version 2 section of the License file that
   32.41 +    accompanied this code. If applicable, add the following below the
   32.42 +    License Header, with the fields enclosed by brackets [] replaced by
   32.43 +    your own identifying information:
   32.44 +    "Portions Copyrighted [year] [name of copyright owner]"
   32.45 +
   32.46 +    Contributor(s):
   32.47 +
   32.48 +    The Original Software is NetBeans. The Initial Developer of the Original
   32.49 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   32.50 +
   32.51 +    If you wish your version of this file to be governed by only the CDDL
   32.52 +    or only the GPL Version 2, indicate your decision by adding
   32.53 +    "[Contributor] elects to include this software in this distribution
   32.54 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
   32.55 +    single choice of license, a recipient has the option to distribute
   32.56 +    your version of this file under either the CDDL, the GPL Version 2 or
   32.57 +    to extend the choice of license to its licensees as provided above.
   32.58 +    However, if you add GPL Version 2 code and therefore, elected the GPL
   32.59 +    Version 2 license, then the option applies only if the new code is
   32.60 +    made subject to such option by the copyright holder.
   32.61  
   32.62  -->
   32.63  <!DOCTYPE html>
    33.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/FindResources.java	Thu Dec 19 17:11:01 2013 +0100
    33.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.3 @@ -1,34 +0,0 @@
    33.4 -/**
    33.5 - * HTML via Java(tm) Language Bindings
    33.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    33.7 - *
    33.8 - * This program is free software: you can redistribute it and/or modify
    33.9 - * it under the terms of the GNU General Public License as published by
   33.10 - * the Free Software Foundation, version 2 of the License.
   33.11 - *
   33.12 - * This program is distributed in the hope that it will be useful,
   33.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   33.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   33.15 - * GNU General Public License for more details. apidesign.org
   33.16 - * designates this particular file as subject to the
   33.17 - * "Classpath" exception as provided by apidesign.org
   33.18 - * in the License file that accompanied this code.
   33.19 - *
   33.20 - * You should have received a copy of the GNU General Public License
   33.21 - * along with this program. Look for COPYING file in the top folder.
   33.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   33.23 - */
   33.24 -package org.apidesign.html.boot.impl;
   33.25 -
   33.26 -import java.net.URL;
   33.27 -import java.util.Collection;
   33.28 -
   33.29 -/**
   33.30 - *
   33.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   33.32 - */
   33.33 -public interface FindResources {
   33.34 -
   33.35 -    public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough);
   33.36 -    
   33.37 -}
    34.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/FnContext.java	Thu Dec 19 17:11:01 2013 +0100
    34.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.3 @@ -1,76 +0,0 @@
    34.4 -/**
    34.5 - * HTML via Java(tm) Language Bindings
    34.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    34.7 - *
    34.8 - * This program is free software: you can redistribute it and/or modify
    34.9 - * it under the terms of the GNU General Public License as published by
   34.10 - * the Free Software Foundation, version 2 of the License.
   34.11 - *
   34.12 - * This program is distributed in the hope that it will be useful,
   34.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   34.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   34.15 - * GNU General Public License for more details. apidesign.org
   34.16 - * designates this particular file as subject to the
   34.17 - * "Classpath" exception as provided by apidesign.org
   34.18 - * in the License file that accompanied this code.
   34.19 - *
   34.20 - * You should have received a copy of the GNU General Public License
   34.21 - * along with this program. Look for COPYING file in the top folder.
   34.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   34.23 - */
   34.24 -package org.apidesign.html.boot.impl;
   34.25 -
   34.26 -import java.io.Closeable;
   34.27 -import java.io.IOException;
   34.28 -import java.util.logging.Logger;
   34.29 -import org.apidesign.html.boot.spi.Fn;
   34.30 -
   34.31 -/**
   34.32 - *
   34.33 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   34.34 - */
   34.35 -public final class FnContext implements Closeable {
   34.36 -    private static final Logger LOG = Logger.getLogger(FnContext.class.getName());
   34.37 -
   34.38 -    private Object prev;
   34.39 -    private FnContext(Fn.Presenter p) {
   34.40 -        this.prev = p;
   34.41 -    }
   34.42 -
   34.43 -    @Override
   34.44 -    public void close() throws IOException {
   34.45 -        if (prev != this) {
   34.46 -            currentPresenter((Fn.Presenter)prev);
   34.47 -            prev = this;
   34.48 -        }
   34.49 -    }
   34.50 -/*
   34.51 -    @Override
   34.52 -    protected void finalize() throws Throwable {
   34.53 -        if (prev != null) {
   34.54 -            LOG.warning("Unclosed context!");
   34.55 -        }
   34.56 -    }
   34.57 -*/
   34.58 -    public static Closeable activate(Fn.Presenter newP) {
   34.59 -        return new FnContext(currentPresenter(newP));
   34.60 -    }
   34.61 -    
   34.62 -    
   34.63 -    private static final ThreadLocal<Fn.Presenter> CURRENT = new ThreadLocal<Fn.Presenter>();
   34.64 -
   34.65 -    public static Fn.Presenter currentPresenter(Fn.Presenter p) {
   34.66 -        Fn.Presenter prev = CURRENT.get();
   34.67 -        CURRENT.set(p);
   34.68 -        return prev;
   34.69 -    }
   34.70 -
   34.71 -    public static Fn.Presenter currentPresenter(boolean canReturnNull) {
   34.72 -        Fn.Presenter p = CURRENT.get();
   34.73 -        if (p == null && !canReturnNull) {
   34.74 -            throw new IllegalStateException("No current WebView context around!");
   34.75 -        }
   34.76 -        return p;
   34.77 -    }
   34.78 -    
   34.79 -}
    35.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/FnUtils.java	Thu Dec 19 17:11:01 2013 +0100
    35.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.3 @@ -1,593 +0,0 @@
    35.4 -/**
    35.5 - * HTML via Java(tm) Language Bindings
    35.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    35.7 - *
    35.8 - * This program is free software: you can redistribute it and/or modify
    35.9 - * it under the terms of the GNU General Public License as published by
   35.10 - * the Free Software Foundation, version 2 of the License.
   35.11 - *
   35.12 - * This program is distributed in the hope that it will be useful,
   35.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   35.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   35.15 - * GNU General Public License for more details. apidesign.org
   35.16 - * designates this particular file as subject to the
   35.17 - * "Classpath" exception as provided by apidesign.org
   35.18 - * in the License file that accompanied this code.
   35.19 - *
   35.20 - * You should have received a copy of the GNU General Public License
   35.21 - * along with this program. Look for COPYING file in the top folder.
   35.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   35.23 - */
   35.24 -package org.apidesign.html.boot.impl;
   35.25 -
   35.26 -import java.io.Closeable;
   35.27 -import java.io.IOException;
   35.28 -import java.io.InputStream;
   35.29 -import java.io.InputStreamReader;
   35.30 -import java.io.Reader;
   35.31 -import java.net.URL;
   35.32 -import java.util.ArrayList;
   35.33 -import java.util.Collections;
   35.34 -import java.util.Enumeration;
   35.35 -import java.util.List;
   35.36 -import java.util.Map;
   35.37 -import java.util.concurrent.Callable;
   35.38 -import org.apidesign.html.boot.spi.Fn;
   35.39 -import org.objectweb.asm.AnnotationVisitor;
   35.40 -import org.objectweb.asm.ClassReader;
   35.41 -import org.objectweb.asm.ClassVisitor;
   35.42 -import org.objectweb.asm.ClassWriter;
   35.43 -import org.objectweb.asm.Label;
   35.44 -import org.objectweb.asm.MethodVisitor;
   35.45 -import org.objectweb.asm.Opcodes;
   35.46 -import org.objectweb.asm.Type;
   35.47 -import org.objectweb.asm.signature.SignatureReader;
   35.48 -import org.objectweb.asm.signature.SignatureVisitor;
   35.49 -import org.objectweb.asm.signature.SignatureWriter;
   35.50 -
   35.51 -/**
   35.52 - *
   35.53 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   35.54 - */
   35.55 -public final class FnUtils implements Fn.Presenter {
   35.56 -    
   35.57 -    private FnUtils() {
   35.58 -    }
   35.59 -    
   35.60 -    /** Seeks for {@link JavaScriptBody} and {@link JavaScriptResource} annotations
   35.61 -     * in the bytecode and converts them into real code. Used by Maven plugin
   35.62 -     * postprocessing classes.
   35.63 -     * 
   35.64 -     * @param bytecode the original bytecode with javascript specific annotations
   35.65 -     * @param loader the loader to load resources (scripts and classes) when needed
   35.66 -     * @return the transformed bytecode
   35.67 -     * @since 0.7
   35.68 -     */
   35.69 -    public static byte[] transform(byte[] bytecode, ClassLoader loader) {
   35.70 -        ClassReader cr = new ClassReader(bytecode) {
   35.71 -            // to allow us to compile with -profile compact1 on 
   35.72 -            // JDK8 while processing the class as JDK7, the highest
   35.73 -            // class format asm 4.1 understands to
   35.74 -            @Override
   35.75 -            public short readShort(int index) {
   35.76 -                short s = super.readShort(index);
   35.77 -                if (index == 6 && s > Opcodes.V1_7) {
   35.78 -                    return Opcodes.V1_7;
   35.79 -                }
   35.80 -                return s;
   35.81 -            }
   35.82 -        };
   35.83 -        FindInClass tst = new FindInClass(loader, null);
   35.84 -        cr.accept(tst, 0);
   35.85 -        if (tst.found > 0) {
   35.86 -            ClassWriter w = new ClassWriterEx(loader, cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
   35.87 -            FindInClass fic = new FindInClass(loader, w);
   35.88 -            cr.accept(fic, 0);
   35.89 -            bytecode = w.toByteArray();
   35.90 -        }
   35.91 -        return bytecode;
   35.92 -    }
   35.93 -    
   35.94 -    public static boolean isJavaScriptCapable(ClassLoader l) {
   35.95 -        if (l instanceof JsClassLoader) {
   35.96 -            return true;
   35.97 -        }
   35.98 -        Class<?> clazz;
   35.99 -        Closeable c = Fn.activate(new FnUtils());
  35.100 -        try {
  35.101 -            clazz = Class.forName(Test.class.getName(), true, l);
  35.102 -            final Object is = ((Callable<?>)clazz.newInstance()).call();
  35.103 -            return Boolean.TRUE.equals(is);
  35.104 -        } catch (Exception ex) {
  35.105 -            return false;
  35.106 -        } finally {
  35.107 -            try {
  35.108 -                c.close();
  35.109 -            } catch (IOException ex) {
  35.110 -                throw new IllegalStateException(ex);
  35.111 -            }
  35.112 -        }
  35.113 -    }
  35.114 -    
  35.115 -    public static boolean isValid(Fn fn) {
  35.116 -        return fn != null && fn.isValid();
  35.117 -    }
  35.118 -
  35.119 -    public static ClassLoader newLoader(final FindResources f, final Fn.Presenter d, ClassLoader parent) {
  35.120 -        return new JsClassLoader(parent) {
  35.121 -            @Override
  35.122 -            protected URL findResource(String name) {
  35.123 -                List<URL> l = res(name, true);
  35.124 -                return l.isEmpty() ? null : l.get(0);
  35.125 -            }
  35.126 -            
  35.127 -            @Override
  35.128 -            protected Enumeration<URL> findResources(String name) {
  35.129 -                return Collections.enumeration(res(name, false));
  35.130 -            }
  35.131 -            
  35.132 -            private List<URL> res(String name, boolean oneIsEnough) {
  35.133 -                List<URL> l = new ArrayList<URL>();
  35.134 -                f.findResources(name, l, oneIsEnough);
  35.135 -                return l;
  35.136 -            }
  35.137 -            
  35.138 -            @Override
  35.139 -            protected Fn defineFn(String code, String... names) {
  35.140 -                return d.defineFn(code, names);
  35.141 -            }
  35.142 -
  35.143 -            @Override
  35.144 -            protected void loadScript(Reader code) throws Exception {
  35.145 -                d.loadScript(code);
  35.146 -            }
  35.147 -        };
  35.148 -    }
  35.149 -
  35.150 -    static String callback(final String body) {
  35.151 -        return new JsCallback() {
  35.152 -            @Override
  35.153 -            protected CharSequence callMethod(
  35.154 -                String ident, String fqn, String method, String params
  35.155 -            ) {
  35.156 -                StringBuilder sb = new StringBuilder();
  35.157 -                sb.append("vm.").append(mangle(fqn, method, params));
  35.158 -                sb.append("(");
  35.159 -                if (ident != null) {
  35.160 -                    sb.append(ident);
  35.161 -                }
  35.162 -                return sb;
  35.163 -            }
  35.164 -
  35.165 -        }.parse(body);
  35.166 -    }
  35.167 -
  35.168 -    static void loadScript(ClassLoader jcl, String resource) {
  35.169 -        final InputStream script = jcl.getResourceAsStream(resource);
  35.170 -        if (script == null) {
  35.171 -            throw new NullPointerException("Can't find " + resource);
  35.172 -        }
  35.173 -        try {
  35.174 -            Reader isr = null;
  35.175 -            try {
  35.176 -                isr = new InputStreamReader(script, "UTF-8");
  35.177 -                FnContext.currentPresenter(false).loadScript(isr);
  35.178 -            } finally {
  35.179 -                if (isr != null) {
  35.180 -                    isr.close();
  35.181 -                }
  35.182 -            }
  35.183 -        } catch (Exception ex) {
  35.184 -            throw new IllegalStateException("Can't execute " + resource, ex);
  35.185 -        } 
  35.186 -    }
  35.187 -
  35.188 -    @Override
  35.189 -    public Fn defineFn(String code, String... names) {
  35.190 -        return new TrueFn();
  35.191 -    }
  35.192 -
  35.193 -    @Override
  35.194 -    public void displayPage(URL page, Runnable onPageLoad) {
  35.195 -    }
  35.196 -
  35.197 -    @Override
  35.198 -    public void loadScript(Reader code) throws Exception {
  35.199 -    }
  35.200 -    
  35.201 -    private static final class FindInClass extends ClassVisitor {
  35.202 -        private String name;
  35.203 -        private int found;
  35.204 -        private ClassLoader loader;
  35.205 -        private String resource;
  35.206 -
  35.207 -        public FindInClass(ClassLoader l, ClassVisitor cv) {
  35.208 -            super(Opcodes.ASM4, cv);
  35.209 -            this.loader = l;
  35.210 -        }
  35.211 -
  35.212 -        @Override
  35.213 -        public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
  35.214 -            this.name = name;
  35.215 -            super.visit(version, access, name, signature, superName, interfaces);
  35.216 -        }
  35.217 -
  35.218 -        @Override
  35.219 -        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
  35.220 -            if ("Lnet/java/html/js/JavaScriptResource;".equals(desc)) {
  35.221 -                return new LoadResource();
  35.222 -            }
  35.223 -            return super.visitAnnotation(desc, visible);
  35.224 -        }
  35.225 -
  35.226 -        @Override
  35.227 -        public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
  35.228 -            return new FindInMethod(access, name, desc,
  35.229 -                    super.visitMethod(access & (~Opcodes.ACC_NATIVE), name, desc, signature, exceptions)
  35.230 -            );
  35.231 -        }
  35.232 -
  35.233 -        private final class FindInMethod extends MethodVisitor {
  35.234 -
  35.235 -            private final String name;
  35.236 -            private final String desc;
  35.237 -            private final int access;
  35.238 -            private List<String> args;
  35.239 -            private String body;
  35.240 -            private boolean bodyGenerated;
  35.241 -
  35.242 -            public FindInMethod(int access, String name, String desc, MethodVisitor mv) {
  35.243 -                super(Opcodes.ASM4, mv);
  35.244 -                this.access = access;
  35.245 -                this.name = name;
  35.246 -                this.desc = desc;
  35.247 -            }
  35.248 -
  35.249 -            @Override
  35.250 -            public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
  35.251 -                if ("Lnet/java/html/js/JavaScriptBody;".equals(desc) // NOI18N
  35.252 -                        || "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;".equals(desc) // NOI18N
  35.253 -                        ) {
  35.254 -                    found++;
  35.255 -                    return new FindInAnno();
  35.256 -                }
  35.257 -                return super.visitAnnotation(desc, visible);
  35.258 -            }
  35.259 -
  35.260 -            private void generateJSBody(List<String> args, String body) {
  35.261 -                this.args = args;
  35.262 -                this.body = body;
  35.263 -            }
  35.264 -
  35.265 -            @Override
  35.266 -            public void visitCode() {
  35.267 -                if (body == null) {
  35.268 -                    return;
  35.269 -                }
  35.270 -                generateBody();
  35.271 -            }
  35.272 -
  35.273 -            private boolean generateBody() {
  35.274 -                if (bodyGenerated) {
  35.275 -                    return false;
  35.276 -                }
  35.277 -                bodyGenerated = true;
  35.278 -
  35.279 -                super.visitFieldInsn(
  35.280 -                        Opcodes.GETSTATIC, FindInClass.this.name,
  35.281 -                        "$$fn$$" + name + "_" + found,
  35.282 -                        "Lorg/apidesign/html/boot/spi/Fn;"
  35.283 -                );
  35.284 -                super.visitInsn(Opcodes.DUP);
  35.285 -                super.visitMethodInsn(
  35.286 -                        Opcodes.INVOKESTATIC,
  35.287 -                        "org/apidesign/html/boot/spi/Fn", "isValid",
  35.288 -                        "(Lorg/apidesign/html/boot/spi/Fn;)Z"
  35.289 -                );
  35.290 -                Label ifNotNull = new Label();
  35.291 -                super.visitJumpInsn(Opcodes.IFNE, ifNotNull);
  35.292 -
  35.293 -                // init Fn
  35.294 -                super.visitInsn(Opcodes.POP);
  35.295 -                super.visitLdcInsn(Type.getObjectType(FindInClass.this.name));
  35.296 -                super.visitLdcInsn(body);
  35.297 -                super.visitIntInsn(Opcodes.SIPUSH, args.size());
  35.298 -                super.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/String");
  35.299 -                boolean needsVM = false;
  35.300 -                for (int i = 0; i < args.size(); i++) {
  35.301 -                    assert !needsVM;
  35.302 -                    String argName = args.get(i);
  35.303 -                    needsVM = "vm".equals(argName);
  35.304 -                    super.visitInsn(Opcodes.DUP);
  35.305 -                    super.visitIntInsn(Opcodes.BIPUSH, i);
  35.306 -                    super.visitLdcInsn(argName);
  35.307 -                    super.visitInsn(Opcodes.AASTORE);
  35.308 -                }
  35.309 -                super.visitMethodInsn(Opcodes.INVOKESTATIC,
  35.310 -                        "org/apidesign/html/boot/spi/Fn", "define",
  35.311 -                        "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/String;)Lorg/apidesign/html/boot/spi/Fn;"
  35.312 -                );
  35.313 -                if (resource != null) {
  35.314 -                    super.visitLdcInsn(Type.getObjectType(FindInClass.this.name));
  35.315 -                    super.visitLdcInsn(resource);
  35.316 -                    super.visitMethodInsn(Opcodes.INVOKESTATIC,
  35.317 -                            "org/apidesign/html/boot/spi/Fn", "preload",
  35.318 -                            "(Lorg/apidesign/html/boot/spi/Fn;Ljava/lang/Class;Ljava/lang/String;)Lorg/apidesign/html/boot/spi/Fn;"
  35.319 -                    );
  35.320 -                }
  35.321 -                super.visitInsn(Opcodes.DUP);
  35.322 -                super.visitFieldInsn(
  35.323 -                        Opcodes.PUTSTATIC, FindInClass.this.name,
  35.324 -                        "$$fn$$" + name + "_" + found,
  35.325 -                        "Lorg/apidesign/html/boot/spi/Fn;"
  35.326 -                );
  35.327 -                // end of Fn init
  35.328 -
  35.329 -                super.visitLabel(ifNotNull);
  35.330 -
  35.331 -                final int offset;
  35.332 -                if ((access & Opcodes.ACC_STATIC) == 0) {
  35.333 -                    offset = 1;
  35.334 -                    super.visitIntInsn(Opcodes.ALOAD, 0);
  35.335 -                } else {
  35.336 -                    offset = 0;
  35.337 -                    super.visitInsn(Opcodes.ACONST_NULL);
  35.338 -                }
  35.339 -
  35.340 -                super.visitIntInsn(Opcodes.SIPUSH, args.size());
  35.341 -                super.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
  35.342 -
  35.343 -                class SV extends SignatureVisitor {
  35.344 -
  35.345 -                    private boolean nowReturn;
  35.346 -                    private Type returnType;
  35.347 -                    private int index;
  35.348 -                    private int loadIndex = offset;
  35.349 -
  35.350 -                    public SV() {
  35.351 -                        super(Opcodes.ASM4);
  35.352 -                    }
  35.353 -
  35.354 -                    @Override
  35.355 -                    public void visitBaseType(char descriptor) {
  35.356 -                        final Type t = Type.getType("" + descriptor);
  35.357 -                        if (nowReturn) {
  35.358 -                            returnType = t;
  35.359 -                            return;
  35.360 -                        }
  35.361 -                        FindInMethod.super.visitInsn(Opcodes.DUP);
  35.362 -                        FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, index++);
  35.363 -                        FindInMethod.super.visitVarInsn(t.getOpcode(Opcodes.ILOAD), loadIndex++);
  35.364 -                        String factory;
  35.365 -                        switch (descriptor) {
  35.366 -                            case 'I':
  35.367 -                                factory = "java/lang/Integer";
  35.368 -                                break;
  35.369 -                            case 'J':
  35.370 -                                factory = "java/lang/Long";
  35.371 -                                loadIndex++;
  35.372 -                                break;
  35.373 -                            case 'S':
  35.374 -                                factory = "java/lang/Short";
  35.375 -                                break;
  35.376 -                            case 'F':
  35.377 -                                factory = "java/lang/Float";
  35.378 -                                break;
  35.379 -                            case 'D':
  35.380 -                                factory = "java/lang/Double";
  35.381 -                                loadIndex++;
  35.382 -                                break;
  35.383 -                            case 'Z':
  35.384 -                                factory = "java/lang/Boolean";
  35.385 -                                break;
  35.386 -                            case 'C':
  35.387 -                                factory = "java/lang/Character";
  35.388 -                                break;
  35.389 -                            case 'B':
  35.390 -                                factory = "java/lang/Byte";
  35.391 -                                break;
  35.392 -                            default:
  35.393 -                                throw new IllegalStateException(t.toString());
  35.394 -                        }
  35.395 -                        FindInMethod.super.visitMethodInsn(Opcodes.INVOKESTATIC,
  35.396 -                                factory, "valueOf", "(" + descriptor + ")L" + factory + ";"
  35.397 -                        );
  35.398 -                        FindInMethod.super.visitInsn(Opcodes.AASTORE);
  35.399 -                    }
  35.400 -
  35.401 -                    @Override
  35.402 -                    public SignatureVisitor visitArrayType() {
  35.403 -                        if (nowReturn) {
  35.404 -                            throw new IllegalStateException("Not supported yet");
  35.405 -                        }
  35.406 -                        loadObject();
  35.407 -                        return new SignatureWriter();
  35.408 -                    }
  35.409 -
  35.410 -                    @Override
  35.411 -                    public void visitClassType(String name) {
  35.412 -                        if (nowReturn) {
  35.413 -                            returnType = Type.getObjectType(name);
  35.414 -                            return;
  35.415 -                        }
  35.416 -                        loadObject();
  35.417 -                    }
  35.418 -
  35.419 -                    @Override
  35.420 -                    public SignatureVisitor visitReturnType() {
  35.421 -                        nowReturn = true;
  35.422 -                        return this;
  35.423 -                    }
  35.424 -
  35.425 -                    private void loadObject() {
  35.426 -                        FindInMethod.super.visitInsn(Opcodes.DUP);
  35.427 -                        FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, index++);
  35.428 -                        FindInMethod.super.visitVarInsn(Opcodes.ALOAD, loadIndex++);
  35.429 -                        FindInMethod.super.visitInsn(Opcodes.AASTORE);
  35.430 -                    }
  35.431 -
  35.432 -                }
  35.433 -                SV sv = new SV();
  35.434 -                SignatureReader sr = new SignatureReader(desc);
  35.435 -                sr.accept(sv);
  35.436 -
  35.437 -                if (needsVM) {
  35.438 -                    FindInMethod.super.visitInsn(Opcodes.DUP);
  35.439 -                    FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, sv.index);
  35.440 -                    int lastSlash = FindInClass.this.name.lastIndexOf('/');
  35.441 -                    String jsCallbacks = FindInClass.this.name.substring(0, lastSlash + 1) + "$JsCallbacks$";
  35.442 -                    FindInMethod.super.visitFieldInsn(Opcodes.GETSTATIC, jsCallbacks, "VM", "L" + jsCallbacks + ";");
  35.443 -                    FindInMethod.super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, jsCallbacks, "current", "()L" + jsCallbacks + ";");
  35.444 -                    FindInMethod.super.visitInsn(Opcodes.AASTORE);
  35.445 -                }
  35.446 -
  35.447 -                super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
  35.448 -                        "org/apidesign/html/boot/spi/Fn", "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"
  35.449 -                );
  35.450 -                switch (sv.returnType.getSort()) {
  35.451 -                    case Type.VOID:
  35.452 -                        super.visitInsn(Opcodes.RETURN);
  35.453 -                        break;
  35.454 -                    case Type.ARRAY:
  35.455 -                    case Type.OBJECT:
  35.456 -                        super.visitTypeInsn(Opcodes.CHECKCAST, sv.returnType.getInternalName());
  35.457 -                        super.visitInsn(Opcodes.ARETURN);
  35.458 -                        break;
  35.459 -                    case Type.BOOLEAN:
  35.460 -                        super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Boolean");
  35.461 -                        super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
  35.462 -                                "java/lang/Boolean", "booleanValue", "()Z"
  35.463 -                        );
  35.464 -                        super.visitInsn(Opcodes.IRETURN);
  35.465 -                        break;
  35.466 -                    default:
  35.467 -                        super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Number");
  35.468 -                        super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
  35.469 -                                "java/lang/Number", sv.returnType.getClassName() + "Value", "()" + sv.returnType.getDescriptor()
  35.470 -                        );
  35.471 -                        super.visitInsn(sv.returnType.getOpcode(Opcodes.IRETURN));
  35.472 -                }
  35.473 -                return true;
  35.474 -            }
  35.475 -
  35.476 -            @Override
  35.477 -            public void visitEnd() {
  35.478 -                super.visitEnd();
  35.479 -                if (body != null) {
  35.480 -                    if (generateBody()) {
  35.481 -                        // native method
  35.482 -                        super.visitMaxs(1, 0);
  35.483 -                    }
  35.484 -                    FindInClass.this.visitField(
  35.485 -                            Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
  35.486 -                            "$$fn$$" + name + "_" + found,
  35.487 -                            "Lorg/apidesign/html/boot/spi/Fn;",
  35.488 -                            null, null
  35.489 -                    );
  35.490 -                }
  35.491 -            }
  35.492 -
  35.493 -            private final class FindInAnno extends AnnotationVisitor {
  35.494 -
  35.495 -                private List<String> args = new ArrayList<String>();
  35.496 -                private String body;
  35.497 -                private boolean javacall = false;
  35.498 -
  35.499 -                public FindInAnno() {
  35.500 -                    super(Opcodes.ASM4);
  35.501 -                }
  35.502 -
  35.503 -                @Override
  35.504 -                public void visit(String name, Object value) {
  35.505 -                    if (name == null) {
  35.506 -                        args.add((String) value);
  35.507 -                        return;
  35.508 -                    }
  35.509 -                    if (name.equals("javacall")) { // NOI18N
  35.510 -                        javacall = (Boolean) value;
  35.511 -                        return;
  35.512 -                    }
  35.513 -                    assert name.equals("body");
  35.514 -                    body = (String) value;
  35.515 -                }
  35.516 -
  35.517 -                @Override
  35.518 -                public AnnotationVisitor visitArray(String name) {
  35.519 -                    return this;
  35.520 -                }
  35.521 -
  35.522 -                @Override
  35.523 -                public void visitEnd() {
  35.524 -                    if (body != null) {
  35.525 -                        if (javacall) {
  35.526 -                            body = callback(body);
  35.527 -                            args.add("vm");
  35.528 -                        }
  35.529 -                        generateJSBody(args, body);
  35.530 -                    }
  35.531 -                }
  35.532 -            }
  35.533 -        }
  35.534 -
  35.535 -        private final class LoadResource extends AnnotationVisitor {
  35.536 -
  35.537 -            public LoadResource() {
  35.538 -                super(Opcodes.ASM4);
  35.539 -            }
  35.540 -
  35.541 -            @Override
  35.542 -            public void visit(String attrName, Object value) {
  35.543 -                String relPath = (String) value;
  35.544 -                if (relPath.startsWith("/")) {
  35.545 -                    resource = relPath;
  35.546 -                } else {
  35.547 -                    int last = name.lastIndexOf('/');
  35.548 -                    String fullPath = name.substring(0, last + 1) + relPath;
  35.549 -                    resource = fullPath;
  35.550 -                }
  35.551 -            }
  35.552 -        }
  35.553 -    }
  35.554 -
  35.555 -    private static class ClassWriterEx extends ClassWriter {
  35.556 -
  35.557 -        private ClassLoader loader;
  35.558 -
  35.559 -        public ClassWriterEx(ClassLoader l, ClassReader classReader, int flags) {
  35.560 -            super(classReader, flags);
  35.561 -            this.loader = l;
  35.562 -        }
  35.563 -
  35.564 -        @Override
  35.565 -        protected String getCommonSuperClass(final String type1, final String type2) {
  35.566 -            Class<?> c, d;
  35.567 -            try {
  35.568 -                c = Class.forName(type1.replace('/', '.'), false, loader);
  35.569 -                d = Class.forName(type2.replace('/', '.'), false, loader);
  35.570 -            } catch (Exception e) {
  35.571 -                throw new RuntimeException(e.toString());
  35.572 -            }
  35.573 -            if (c.isAssignableFrom(d)) {
  35.574 -                return type1;
  35.575 -            }
  35.576 -            if (d.isAssignableFrom(c)) {
  35.577 -                return type2;
  35.578 -            }
  35.579 -            if (c.isInterface() || d.isInterface()) {
  35.580 -                return "java/lang/Object";
  35.581 -            } else {
  35.582 -                do {
  35.583 -                    c = c.getSuperclass();
  35.584 -                } while (!c.isAssignableFrom(d));
  35.585 -                return c.getName().replace('.', '/');
  35.586 -            }
  35.587 -        }
  35.588 -    }
  35.589 -
  35.590 -    private static final class TrueFn extends Fn {
  35.591 -        @Override
  35.592 -        public Object invoke(Object thiz, Object... args) throws Exception {
  35.593 -            return Boolean.TRUE;
  35.594 -        }
  35.595 -    } // end of TrueFn
  35.596 -}
    36.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/JavaScriptProcesor.java	Thu Dec 19 17:11:01 2013 +0100
    36.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.3 @@ -1,347 +0,0 @@
    36.4 -/**
    36.5 - * HTML via Java(tm) Language Bindings
    36.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    36.7 - *
    36.8 - * This program is free software: you can redistribute it and/or modify
    36.9 - * it under the terms of the GNU General Public License as published by
   36.10 - * the Free Software Foundation, version 2 of the License.
   36.11 - *
   36.12 - * This program is distributed in the hope that it will be useful,
   36.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   36.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   36.15 - * GNU General Public License for more details. apidesign.org
   36.16 - * designates this particular file as subject to the
   36.17 - * "Classpath" exception as provided by apidesign.org
   36.18 - * in the License file that accompanied this code.
   36.19 - *
   36.20 - * You should have received a copy of the GNU General Public License
   36.21 - * along with this program. Look for COPYING file in the top folder.
   36.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   36.23 - */
   36.24 -package org.apidesign.html.boot.impl;
   36.25 -
   36.26 -import java.io.IOException;
   36.27 -import java.io.Writer;
   36.28 -import java.util.Collections;
   36.29 -import java.util.HashMap;
   36.30 -import java.util.HashSet;
   36.31 -import java.util.List;
   36.32 -import java.util.Map;
   36.33 -import java.util.Set;
   36.34 -import java.util.TreeMap;
   36.35 -import javax.annotation.processing.AbstractProcessor;
   36.36 -import javax.annotation.processing.Completion;
   36.37 -import javax.annotation.processing.Completions;
   36.38 -import javax.annotation.processing.Messager;
   36.39 -import javax.annotation.processing.Processor;
   36.40 -import javax.annotation.processing.RoundEnvironment;
   36.41 -import javax.lang.model.SourceVersion;
   36.42 -import javax.lang.model.element.AnnotationMirror;
   36.43 -import javax.lang.model.element.Element;
   36.44 -import javax.lang.model.element.ElementKind;
   36.45 -import javax.lang.model.element.ExecutableElement;
   36.46 -import javax.lang.model.element.Modifier;
   36.47 -import javax.lang.model.element.PackageElement;
   36.48 -import javax.lang.model.element.TypeElement;
   36.49 -import javax.lang.model.element.VariableElement;
   36.50 -import javax.lang.model.type.ArrayType;
   36.51 -import javax.lang.model.type.ExecutableType;
   36.52 -import javax.lang.model.type.TypeKind;
   36.53 -import javax.lang.model.type.TypeMirror;
   36.54 -import javax.tools.Diagnostic;
   36.55 -import javax.tools.FileObject;
   36.56 -import javax.tools.StandardLocation;
   36.57 -import net.java.html.js.JavaScriptBody;
   36.58 -import net.java.html.js.JavaScriptResource;
   36.59 -import org.openide.util.lookup.ServiceProvider;
   36.60 -
   36.61 -/**
   36.62 - *
   36.63 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   36.64 - */
   36.65 -@ServiceProvider(service = Processor.class)
   36.66 -public final class JavaScriptProcesor extends AbstractProcessor {
   36.67 -    private final Map<String,Map<String,ExecutableElement>> javacalls = 
   36.68 -        new HashMap<String,Map<String,ExecutableElement>>();
   36.69 -    
   36.70 -    @Override
   36.71 -    public Set<String> getSupportedAnnotationTypes() {
   36.72 -        Set<String> set = new HashSet<String>();
   36.73 -        set.add(JavaScriptBody.class.getName());
   36.74 -        set.add(JavaScriptResource.class.getName());
   36.75 -        return set;
   36.76 -    }
   36.77 -    
   36.78 -    @Override
   36.79 -    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
   36.80 -        final Messager msg = processingEnv.getMessager();
   36.81 -        for (Element e : roundEnv.getElementsAnnotatedWith(JavaScriptBody.class)) {
   36.82 -            if (e.getKind() != ElementKind.METHOD && e.getKind() != ElementKind.CONSTRUCTOR) {
   36.83 -                continue;
   36.84 -            }
   36.85 -            ExecutableElement ee = (ExecutableElement)e;
   36.86 -            List<? extends VariableElement> params = ee.getParameters();
   36.87 -            
   36.88 -            JavaScriptBody jsb = e.getAnnotation(JavaScriptBody.class);
   36.89 -            if (jsb == null) {
   36.90 -                continue;
   36.91 -            }
   36.92 -            String[] arr = jsb.args();
   36.93 -            if (params.size() != arr.length) {
   36.94 -                msg.printMessage(Diagnostic.Kind.ERROR, "Number of args arguments does not match real arguments!", e);
   36.95 -            }
   36.96 -            if (!jsb.javacall() && jsb.body().contains(".@")) {
   36.97 -                msg.printMessage(Diagnostic.Kind.WARNING, "Usage of .@ usually requires javacall=true", e);
   36.98 -            }
   36.99 -            if (jsb.javacall()) {
  36.100 -                JsCallback verify = new VerifyCallback(e);
  36.101 -                try {
  36.102 -                    verify.parse(jsb.body());
  36.103 -                } catch (IllegalStateException ex) {
  36.104 -                    msg.printMessage(Diagnostic.Kind.ERROR, ex.getLocalizedMessage(), e);
  36.105 -                }
  36.106 -            }
  36.107 -        }
  36.108 -        for (Element e : roundEnv.getElementsAnnotatedWith(JavaScriptResource.class)) {
  36.109 -            JavaScriptResource r = e.getAnnotation(JavaScriptResource.class);
  36.110 -            if (r == null) {
  36.111 -                continue;
  36.112 -            }
  36.113 -            final String res;
  36.114 -            if (r.value().startsWith("/")) {
  36.115 -                res = r.value();
  36.116 -            } else {
  36.117 -                res = findPkg(e).replace('.', '/') + "/" + r.value();
  36.118 -            }
  36.119 -            
  36.120 -            try {
  36.121 -                FileObject os = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", res);
  36.122 -                os.openInputStream().close();
  36.123 -            } catch (IOException ex1) {
  36.124 -                try {
  36.125 -                    FileObject os2 = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", res);
  36.126 -                    os2.openInputStream().close();
  36.127 -                } catch (IOException ex2) {
  36.128 -                    msg.printMessage(Diagnostic.Kind.ERROR, "Cannot find " + res + " in " + res + " package", e);
  36.129 -                }
  36.130 -            }
  36.131 -        }
  36.132 -
  36.133 -        if (roundEnv.processingOver()) {
  36.134 -            generateCallbackClass(javacalls);
  36.135 -            javacalls.clear();
  36.136 -        }
  36.137 -        return true;
  36.138 -    }
  36.139 -
  36.140 -    @Override
  36.141 -    public Iterable<? extends Completion> getCompletions(Element e, 
  36.142 -        AnnotationMirror annotation, ExecutableElement member, String userText
  36.143 -    ) {
  36.144 -        StringBuilder sb = new StringBuilder();
  36.145 -        if (e.getKind() == ElementKind.METHOD && member.getSimpleName().contentEquals("args")) {
  36.146 -            ExecutableElement ee = (ExecutableElement) e;
  36.147 -            String sep = "";
  36.148 -            sb.append("{ ");
  36.149 -            for (VariableElement ve : ee.getParameters()) {
  36.150 -                sb.append(sep).append('"').append(ve.getSimpleName())
  36.151 -                    .append('"');
  36.152 -                sep = ", ";
  36.153 -            }
  36.154 -            sb.append(" }");
  36.155 -            return Collections.nCopies(1, Completions.of(sb.toString()));
  36.156 -        }
  36.157 -        return null;
  36.158 -    }
  36.159 -
  36.160 -    private class VerifyCallback extends JsCallback {
  36.161 -        private final Element e;
  36.162 -        public VerifyCallback(Element e) {
  36.163 -            this.e = e;
  36.164 -        }
  36.165 -
  36.166 -        @Override
  36.167 -        protected CharSequence callMethod(String ident, String fqn, String method, String params) {
  36.168 -            final TypeElement type = processingEnv.getElementUtils().getTypeElement(fqn);
  36.169 -            if (type == null) {
  36.170 -                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, 
  36.171 -                    "Callback to non-existing class " + fqn, e
  36.172 -                );
  36.173 -                return "";
  36.174 -            }
  36.175 -            ExecutableElement found = null;
  36.176 -            StringBuilder foundParams = new StringBuilder();
  36.177 -            for (Element m : type.getEnclosedElements()) {
  36.178 -                if (m.getKind() != ElementKind.METHOD) {
  36.179 -                    continue;
  36.180 -                }
  36.181 -                if (m.getSimpleName().contentEquals(method)) {
  36.182 -                    String paramTypes = findParamTypes((ExecutableElement)m);
  36.183 -                    if (paramTypes.equals(params)) {
  36.184 -                        found = (ExecutableElement) m;
  36.185 -                        break;
  36.186 -                    }
  36.187 -                    foundParams.append(paramTypes).append("\n");
  36.188 -                }
  36.189 -            }
  36.190 -            if (found == null) {
  36.191 -                if (foundParams.length() == 0) {
  36.192 -                    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, 
  36.193 -                        "Callback to class " + fqn + " with unknown method " + method, e
  36.194 -                    );
  36.195 -                } else {
  36.196 -                    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, 
  36.197 -                        "Callback to " + fqn + "." + method + " with wrong parameters: " + 
  36.198 -                        params + ". Only known parameters are " + foundParams, e
  36.199 -                    );
  36.200 -                }
  36.201 -            } else {
  36.202 -                Map<String,ExecutableElement> mangledOnes = javacalls.get(findPkg(e));
  36.203 -                if (mangledOnes == null) {
  36.204 -                    mangledOnes = new TreeMap<String, ExecutableElement>();
  36.205 -                    javacalls.put(findPkg(e), mangledOnes);
  36.206 -                }
  36.207 -                String mangled = JsCallback.mangle(fqn, method, findParamTypes(found));
  36.208 -                mangledOnes.put(mangled, found);
  36.209 -            }
  36.210 -            return "";
  36.211 -        }
  36.212 -
  36.213 -        private String findParamTypes(ExecutableElement method) {
  36.214 -            ExecutableType t = (ExecutableType) method.asType();
  36.215 -            StringBuilder sb = new StringBuilder();
  36.216 -            sb.append('(');
  36.217 -            for (TypeMirror tm : t.getParameterTypes()) {
  36.218 -                if (tm.getKind().isPrimitive()) {
  36.219 -                    switch (tm.getKind()) {
  36.220 -                        case INT: sb.append('I'); break;
  36.221 -                        case BOOLEAN: sb.append('Z'); break;
  36.222 -                        case BYTE: sb.append('B'); break;
  36.223 -                        case CHAR: sb.append('C'); break;
  36.224 -                        case SHORT: sb.append('S'); break;
  36.225 -                        case DOUBLE: sb.append('D'); break;
  36.226 -                        case FLOAT: sb.append('F'); break;
  36.227 -                        case LONG: sb.append('J'); break;
  36.228 -                        default:
  36.229 -                            throw new IllegalStateException("Uknown " + tm.getKind());
  36.230 -                    }
  36.231 -                } else {
  36.232 -                    while (tm.getKind() == TypeKind.ARRAY) {
  36.233 -                        sb.append('[');
  36.234 -                        tm = ((ArrayType)tm).getComponentType();
  36.235 -                    }
  36.236 -                    sb.append('L');
  36.237 -                    sb.append(tm.toString().replace('.', '/'));
  36.238 -                    sb.append(';');
  36.239 -                }
  36.240 -            }
  36.241 -            sb.append(')');
  36.242 -            return sb.toString();
  36.243 -        }
  36.244 -    }
  36.245 -    
  36.246 -    private void generateCallbackClass(Map<String,Map<String, ExecutableElement>> process) {
  36.247 -        for (Map.Entry<String, Map<String, ExecutableElement>> pkgEn : process.entrySet()) {
  36.248 -            String pkgName = pkgEn.getKey();
  36.249 -            Map<String, ExecutableElement> map = pkgEn.getValue();
  36.250 -            StringBuilder source = new StringBuilder();
  36.251 -            source.append("package ").append(pkgName).append(";\n");
  36.252 -            source.append("public final class $JsCallbacks$ {\n");
  36.253 -            source.append("  static final $JsCallbacks$ VM = new $JsCallbacks$(null);\n");
  36.254 -            source.append("  private final org.apidesign.html.boot.spi.Fn.Presenter p;\n");
  36.255 -            source.append("  private $JsCallbacks$ last;\n");
  36.256 -            source.append("  private $JsCallbacks$(org.apidesign.html.boot.spi.Fn.Presenter p) {\n");
  36.257 -            source.append("    this.p = p;\n");
  36.258 -            source.append("  }\n");
  36.259 -            source.append("  final $JsCallbacks$ current() {\n");
  36.260 -            source.append("    org.apidesign.html.boot.spi.Fn.Presenter now = org.apidesign.html.boot.spi.Fn.activePresenter();\n");
  36.261 -            source.append("    if (now == p) return this;\n");
  36.262 -            source.append("    if (last != null && now == last.p) return last;\n");
  36.263 -            source.append("    return last = new $JsCallbacks$(now);\n");
  36.264 -            source.append("  }\n");
  36.265 -            for (Map.Entry<String, ExecutableElement> entry : map.entrySet()) {
  36.266 -                final String mangled = entry.getKey();
  36.267 -                final ExecutableElement m = entry.getValue();
  36.268 -                final boolean isStatic = m.getModifiers().contains(Modifier.STATIC);
  36.269 -                
  36.270 -                source.append("\n  public java.lang.Object ")
  36.271 -                    .append(mangled)
  36.272 -                    .append("(");
  36.273 -                
  36.274 -                String sep = "";
  36.275 -                if (!isStatic) {
  36.276 -                    source.append(((TypeElement)m.getEnclosingElement()).getQualifiedName());
  36.277 -                    source.append(" self");
  36.278 -                    sep = ", ";
  36.279 -                }
  36.280 -                
  36.281 -                int cnt = 0;
  36.282 -                for (VariableElement ve : m.getParameters()) {
  36.283 -                    source.append(sep);
  36.284 -                    source.append(ve.asType());
  36.285 -                    source.append(" arg").append(++cnt);
  36.286 -                    sep = ", ";
  36.287 -                }
  36.288 -                source.append(") throws Throwable {\n");
  36.289 -                if (processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_7) >= 0) {
  36.290 -                    source.append("    try (java.io.Closeable a = org.apidesign.html.boot.spi.Fn.activate(p)) { \n");
  36.291 -                } else {
  36.292 -                    source.append("    java.io.Closeable a = org.apidesign.html.boot.spi.Fn.activate(p); try {\n");
  36.293 -                }
  36.294 -                source.append("    ");
  36.295 -                if (m.getReturnType().getKind() != TypeKind.VOID) {
  36.296 -                    source.append("return ");
  36.297 -                }
  36.298 -                if (isStatic) {
  36.299 -                    source.append(((TypeElement)m.getEnclosingElement()).getQualifiedName());
  36.300 -                    source.append('.');
  36.301 -                } else {
  36.302 -                    source.append("self.");
  36.303 -                }
  36.304 -                source.append(m.getSimpleName());
  36.305 -                source.append("(");
  36.306 -                cnt = 0;
  36.307 -                sep = "";
  36.308 -                for (VariableElement ve : m.getParameters()) {
  36.309 -                    source.append(sep);
  36.310 -                    source.append("arg").append(++cnt);
  36.311 -                    sep = ", ";
  36.312 -                }
  36.313 -                source.append(");\n");
  36.314 -                if (m.getReturnType().getKind() == TypeKind.VOID) {
  36.315 -                    source.append("    return null;\n");
  36.316 -                }
  36.317 -                if (processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_7) >= 0) {
  36.318 -                    source.append("    }\n");
  36.319 -                } else {
  36.320 -                    
  36.321 -                    source.append("    } finally {\n");
  36.322 -                    source.append("      a.close();\n");
  36.323 -                    source.append("    }\n");
  36.324 -                }
  36.325 -                source.append("  }\n");
  36.326 -            }
  36.327 -            source.append("}\n");
  36.328 -            final String srcName = pkgName + ".$JsCallbacks$";
  36.329 -            try {
  36.330 -                Writer w = processingEnv.getFiler().createSourceFile(srcName,
  36.331 -                    map.values().toArray(new Element[map.size()])
  36.332 -                ).openWriter();
  36.333 -                w.write(source.toString());
  36.334 -                w.close();
  36.335 -            } catch (IOException ex) {
  36.336 -                processingEnv.getMessager().printMessage(
  36.337 -                    Diagnostic.Kind.ERROR, "Can't write " + srcName + ": " + ex.getMessage()
  36.338 -                );
  36.339 -            }
  36.340 -        }
  36.341 -    }
  36.342 -    
  36.343 -    private static String findPkg(Element e) {
  36.344 -        while (e.getKind() != ElementKind.PACKAGE) {
  36.345 -            e = e.getEnclosingElement();
  36.346 -        }
  36.347 -        return ((PackageElement)e).getQualifiedName().toString();
  36.348 -    }
  36.349 -    
  36.350 -}
    37.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/JsAgent.java	Thu Dec 19 17:11:01 2013 +0100
    37.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.3 @@ -1,45 +0,0 @@
    37.4 -/**
    37.5 - * HTML via Java(tm) Language Bindings
    37.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    37.7 - *
    37.8 - * This program is free software: you can redistribute it and/or modify
    37.9 - * it under the terms of the GNU General Public License as published by
   37.10 - * the Free Software Foundation, version 2 of the License.
   37.11 - *
   37.12 - * This program is distributed in the hope that it will be useful,
   37.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   37.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   37.15 - * GNU General Public License for more details. apidesign.org
   37.16 - * designates this particular file as subject to the
   37.17 - * "Classpath" exception as provided by apidesign.org
   37.18 - * in the License file that accompanied this code.
   37.19 - *
   37.20 - * You should have received a copy of the GNU General Public License
   37.21 - * along with this program. Look for COPYING file in the top folder.
   37.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   37.23 - */
   37.24 -package org.apidesign.html.boot.impl;
   37.25 -
   37.26 -import java.lang.instrument.ClassFileTransformer;
   37.27 -import java.lang.instrument.IllegalClassFormatException;
   37.28 -import java.lang.instrument.Instrumentation;
   37.29 -import java.security.ProtectionDomain;
   37.30 -
   37.31 -/**
   37.32 - *
   37.33 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   37.34 - */
   37.35 -public final class JsAgent implements ClassFileTransformer {
   37.36 -    public static void agentmain(String args, Instrumentation instr) {
   37.37 -        instr.addTransformer(new JsAgent());
   37.38 -    }
   37.39 -
   37.40 -    @Override
   37.41 -    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
   37.42 -        try {
   37.43 -            return FnUtils.transform(classfileBuffer, loader);
   37.44 -        } catch (Exception ex) {
   37.45 -            return classfileBuffer;
   37.46 -        }
   37.47 -    }
   37.48 -}
    38.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/JsCallback.java	Thu Dec 19 17:11:01 2013 +0100
    38.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.3 @@ -1,138 +0,0 @@
    38.4 -/**
    38.5 - * HTML via Java(tm) Language Bindings
    38.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    38.7 - *
    38.8 - * This program is free software: you can redistribute it and/or modify
    38.9 - * it under the terms of the GNU General Public License as published by
   38.10 - * the Free Software Foundation, version 2 of the License.
   38.11 - *
   38.12 - * This program is distributed in the hope that it will be useful,
   38.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   38.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   38.15 - * GNU General Public License for more details. apidesign.org
   38.16 - * designates this particular file as subject to the
   38.17 - * "Classpath" exception as provided by apidesign.org
   38.18 - * in the License file that accompanied this code.
   38.19 - *
   38.20 - * You should have received a copy of the GNU General Public License
   38.21 - * along with this program. Look for COPYING file in the top folder.
   38.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   38.23 - */
   38.24 -package org.apidesign.html.boot.impl;
   38.25 -
   38.26 -
   38.27 -/**
   38.28 - *
   38.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   38.30 - */
   38.31 -abstract class JsCallback {
   38.32 -    final String parse(String body) {
   38.33 -        StringBuilder sb = new StringBuilder();
   38.34 -        int pos = 0;
   38.35 -        for (;;) {
   38.36 -            int next = body.indexOf(".@", pos);
   38.37 -            if (next == -1) {
   38.38 -                sb.append(body.substring(pos));
   38.39 -                body = sb.toString();
   38.40 -                break;
   38.41 -            }
   38.42 -            int ident = next;
   38.43 -            while (ident > 0) {
   38.44 -                if (!Character.isJavaIdentifierPart(body.charAt(--ident))) {
   38.45 -                    ident++;
   38.46 -                    break;
   38.47 -                }
   38.48 -            }
   38.49 -            String refId = body.substring(ident, next);
   38.50 -            
   38.51 -            sb.append(body.substring(pos, ident));
   38.52 -            
   38.53 -            int sigBeg = body.indexOf('(', next);
   38.54 -            int sigEnd = body.indexOf(')', sigBeg);
   38.55 -            int colon4 = body.indexOf("::", next);
   38.56 -            if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
   38.57 -                throw new IllegalStateException(
   38.58 -                    "Wrong format of instance callback. "
   38.59 -                    + "Should be: 'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n" 
   38.60 -                    + body
   38.61 -                );
   38.62 -            }
   38.63 -            String fqn = body.substring(next + 2, colon4);
   38.64 -            String method = body.substring(colon4 + 2, sigBeg);
   38.65 -            String params = body.substring(sigBeg, sigEnd + 1);
   38.66 -
   38.67 -            int paramBeg = body.indexOf('(', sigEnd + 1);
   38.68 -            if (paramBeg == -1) {
   38.69 -                throw new IllegalStateException(
   38.70 -                    "Wrong format of instance callback. "
   38.71 -                    + "Should be: 'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n" 
   38.72 -                    + body
   38.73 -                );
   38.74 -            }
   38.75 -            
   38.76 -            sb.append(callMethod(refId, fqn, method, params));
   38.77 -            if (body.charAt(paramBeg + 1) != (')')) {
   38.78 -                sb.append(",");
   38.79 -            }
   38.80 -            pos = paramBeg + 1;
   38.81 -        }
   38.82 -        pos = 0;
   38.83 -        sb = null;
   38.84 -        for (;;) {
   38.85 -            int next = body.indexOf("@", pos);
   38.86 -            if (next == -1) {
   38.87 -                if (sb == null) {
   38.88 -                    return body;
   38.89 -                }
   38.90 -                sb.append(body.substring(pos));
   38.91 -                return sb.toString();
   38.92 -            }
   38.93 -            if (sb == null) {
   38.94 -                sb = new StringBuilder();
   38.95 -            }
   38.96 -            
   38.97 -            sb.append(body.substring(pos, next));
   38.98 -            
   38.99 -            int sigBeg = body.indexOf('(', next);
  38.100 -            int sigEnd = body.indexOf(')', sigBeg);
  38.101 -            int colon4 = body.indexOf("::", next);
  38.102 -            if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
  38.103 -                throw new IllegalStateException(
  38.104 -                    "Wrong format of static callback. "
  38.105 -                    + "Should be: '@pkg.Class::staticMethod(Ljava/lang/Object;)(param)':\n" 
  38.106 -                    + body
  38.107 -                );
  38.108 -            }
  38.109 -            String fqn = body.substring(next + 1, colon4);
  38.110 -            String method = body.substring(colon4 + 2, sigBeg);
  38.111 -            String params = body.substring(sigBeg, sigEnd + 1);
  38.112 -
  38.113 -            int paramBeg = body.indexOf('(', sigEnd + 1);
  38.114 -            
  38.115 -            sb.append(callMethod(null, fqn, method, params));
  38.116 -            pos = paramBeg + 1;
  38.117 -        }
  38.118 -    }
  38.119 -
  38.120 -    protected abstract CharSequence callMethod(
  38.121 -        String ident, String fqn, String method, String params
  38.122 -    );
  38.123 -
  38.124 -    static String mangle(String fqn, String method, String params) {
  38.125 -        if (params.startsWith("(")) {
  38.126 -            params = params.substring(1);
  38.127 -        }
  38.128 -        if (params.endsWith(")")) {
  38.129 -            params = params.substring(0, params.length() - 1);
  38.130 -        }
  38.131 -        return 
  38.132 -            replace(fqn) + "$" + replace(method) + "$" + replace(params);
  38.133 -    }
  38.134 -    
  38.135 -    private static String replace(String orig) {
  38.136 -        return orig.replace("_", "_1").
  38.137 -            replace(";", "_2").
  38.138 -            replace("[", "_3").
  38.139 -            replace('.', '_').replace('/', '_');
  38.140 -    }
  38.141 -}
    39.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/JsClassLoader.java	Thu Dec 19 17:11:01 2013 +0100
    39.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.3 @@ -1,111 +0,0 @@
    39.4 -/**
    39.5 - * HTML via Java(tm) Language Bindings
    39.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    39.7 - *
    39.8 - * This program is free software: you can redistribute it and/or modify
    39.9 - * it under the terms of the GNU General Public License as published by
   39.10 - * the Free Software Foundation, version 2 of the License.
   39.11 - *
   39.12 - * This program is distributed in the hope that it will be useful,
   39.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   39.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   39.15 - * GNU General Public License for more details. apidesign.org
   39.16 - * designates this particular file as subject to the
   39.17 - * "Classpath" exception as provided by apidesign.org
   39.18 - * in the License file that accompanied this code.
   39.19 - *
   39.20 - * You should have received a copy of the GNU General Public License
   39.21 - * along with this program. Look for COPYING file in the top folder.
   39.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   39.23 - */
   39.24 -package org.apidesign.html.boot.impl;
   39.25 -
   39.26 -import org.apidesign.html.boot.spi.Fn;
   39.27 -import java.io.IOException;
   39.28 -import java.io.InputStream;
   39.29 -import java.io.Reader;
   39.30 -import java.net.URL;
   39.31 -import java.util.Enumeration;
   39.32 -
   39.33 -/** 
   39.34 - *
   39.35 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   39.36 - */
   39.37 -abstract class JsClassLoader extends ClassLoader {
   39.38 -    JsClassLoader(ClassLoader parent) {
   39.39 -        super(parent);
   39.40 -        setDefaultAssertionStatus(JsClassLoader.class.desiredAssertionStatus());
   39.41 -    }
   39.42 -    
   39.43 -    @Override
   39.44 -    protected abstract URL findResource(String name);
   39.45 -    
   39.46 -    @Override
   39.47 -    protected abstract Enumeration<URL> findResources(String name);
   39.48 -
   39.49 -    @Override
   39.50 -    protected Class<?> findClass(String name) throws ClassNotFoundException {
   39.51 -        if (name.startsWith("javafx")) {
   39.52 -            return Class.forName(name);
   39.53 -        }
   39.54 -        if (name.startsWith("netscape")) {
   39.55 -            return Class.forName(name);
   39.56 -        }
   39.57 -        if (name.startsWith("com.sun")) {
   39.58 -            return Class.forName(name);
   39.59 -        }
   39.60 -        if (name.equals(JsClassLoader.class.getName())) {
   39.61 -            return JsClassLoader.class;
   39.62 -        }
   39.63 -        if (name.equals(Fn.class.getName())) {
   39.64 -            return Fn.class;
   39.65 -        }
   39.66 -        if (name.equals(Fn.Presenter.class.getName())) {
   39.67 -            return Fn.Presenter.class;
   39.68 -        }
   39.69 -        if (name.equals(FnUtils.class.getName())) {
   39.70 -            return FnUtils.class;
   39.71 -        }
   39.72 -        if (
   39.73 -            name.equals("org.apidesign.html.boot.spi.Fn") ||
   39.74 -            name.equals("org.apidesign.html.boot.impl.FnUtils") ||
   39.75 -            name.equals("org.apidesign.html.boot.impl.FnContext")
   39.76 -        ) {
   39.77 -            return Class.forName(name);
   39.78 -        }
   39.79 -        URL u = findResource(name.replace('.', '/') + ".class");
   39.80 -        if (u != null) {
   39.81 -            InputStream is = null;
   39.82 -            try {
   39.83 -                is = u.openStream();
   39.84 -                byte[] arr = new byte[is.available()];
   39.85 -                int len = 0;
   39.86 -                while (len < arr.length) {
   39.87 -                    int read = is.read(arr, len, arr.length - len);
   39.88 -                    if (read == -1) {
   39.89 -                        throw new IOException("Can't read " + u);
   39.90 -                    }
   39.91 -                    len += read;
   39.92 -                }
   39.93 -                is.close();
   39.94 -                is = null;
   39.95 -                arr = FnUtils.transform(arr, JsClassLoader.this);
   39.96 -                if (arr != null) {
   39.97 -                    return defineClass(name, arr, 0, arr.length);
   39.98 -                }
   39.99 -            } catch (IOException ex) {
  39.100 -                throw new ClassNotFoundException("Can't load " + name, ex);
  39.101 -            } finally {
  39.102 -                try {
  39.103 -                    if (is != null) is.close();
  39.104 -                } catch (IOException ex) {
  39.105 -                    throw new ClassNotFoundException(null, ex);
  39.106 -                }
  39.107 -            }
  39.108 -        }
  39.109 -        return super.findClass(name);
  39.110 -    }
  39.111 -    
  39.112 -    protected abstract Fn defineFn(String code, String... names);
  39.113 -    protected abstract void loadScript(Reader code) throws Exception;
  39.114 -}
    40.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/Test.java	Thu Dec 19 17:11:01 2013 +0100
    40.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.3 @@ -1,35 +0,0 @@
    40.4 -/**
    40.5 - * HTML via Java(tm) Language Bindings
    40.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    40.7 - *
    40.8 - * This program is free software: you can redistribute it and/or modify
    40.9 - * it under the terms of the GNU General Public License as published by
   40.10 - * the Free Software Foundation, version 2 of the License.
   40.11 - *
   40.12 - * This program is distributed in the hope that it will be useful,
   40.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   40.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   40.15 - * GNU General Public License for more details. apidesign.org
   40.16 - * designates this particular file as subject to the
   40.17 - * "Classpath" exception as provided by apidesign.org
   40.18 - * in the License file that accompanied this code.
   40.19 - *
   40.20 - * You should have received a copy of the GNU General Public License
   40.21 - * along with this program. Look for COPYING file in the top folder.
   40.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   40.23 - */
   40.24 -package org.apidesign.html.boot.impl;
   40.25 -
   40.26 -import java.util.concurrent.Callable;
   40.27 -import net.java.html.js.JavaScriptBody;
   40.28 -
   40.29 -/**
   40.30 - *
   40.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   40.32 - */
   40.33 -public final class Test implements Callable<Boolean> {
   40.34 -    @Override @JavaScriptBody(args = {}, body = "return true;")
   40.35 -    public Boolean call() {
   40.36 -        return false;
   40.37 -    }
   40.38 -}
    41.1 --- a/boot/src/main/java/org/apidesign/html/boot/spi/Fn.java	Thu Dec 19 17:11:01 2013 +0100
    41.2 +++ b/boot/src/main/java/org/apidesign/html/boot/spi/Fn.java	Tue Jan 07 08:21:57 2014 +0100
    41.3 @@ -1,22 +1,44 @@
    41.4  /**
    41.5 - * HTML via Java(tm) Language Bindings
    41.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    41.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    41.8   *
    41.9 - * This program is free software: you can redistribute it and/or modify
   41.10 - * it under the terms of the GNU General Public License as published by
   41.11 - * the Free Software Foundation, version 2 of the License.
   41.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   41.13   *
   41.14 - * This program is distributed in the hope that it will be useful,
   41.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   41.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   41.17 - * GNU General Public License for more details. apidesign.org
   41.18 - * designates this particular file as subject to the
   41.19 - * "Classpath" exception as provided by apidesign.org
   41.20 - * in the License file that accompanied this code.
   41.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   41.22 + * Other names may be trademarks of their respective owners.
   41.23   *
   41.24 - * You should have received a copy of the GNU General Public License
   41.25 - * along with this program. Look for COPYING file in the top folder.
   41.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   41.27 + * The contents of this file are subject to the terms of either the GNU
   41.28 + * General Public License Version 2 only ("GPL") or the Common
   41.29 + * Development and Distribution License("CDDL") (collectively, the
   41.30 + * "License"). You may not use this file except in compliance with the
   41.31 + * License. You can obtain a copy of the License at
   41.32 + * http://www.netbeans.org/cddl-gplv2.html
   41.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   41.34 + * specific language governing permissions and limitations under the
   41.35 + * License.  When distributing the software, include this License Header
   41.36 + * Notice in each file and include the License file at
   41.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   41.38 + * particular file as subject to the "Classpath" exception as provided
   41.39 + * by Oracle in the GPL Version 2 section of the License file that
   41.40 + * accompanied this code. If applicable, add the following below the
   41.41 + * License Header, with the fields enclosed by brackets [] replaced by
   41.42 + * your own identifying information:
   41.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   41.44 + *
   41.45 + * Contributor(s):
   41.46 + *
   41.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   41.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   41.49 + *
   41.50 + * If you wish your version of this file to be governed by only the CDDL
   41.51 + * or only the GPL Version 2, indicate your decision by adding
   41.52 + * "[Contributor] elects to include this software in this distribution
   41.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   41.54 + * single choice of license, a recipient has the option to distribute
   41.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   41.56 + * to extend the choice of license to its licensees as provided above.
   41.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   41.58 + * Version 2 license, then the option applies only if the new code is
   41.59 + * made subject to such option by the copyright holder.
   41.60   */
   41.61  package org.apidesign.html.boot.spi;
   41.62  
   41.63 @@ -29,9 +51,8 @@
   41.64  import java.util.HashSet;
   41.65  import java.util.Map;
   41.66  import java.util.Set;
   41.67 -import java.util.WeakHashMap;
   41.68  import net.java.html.js.JavaScriptBody;
   41.69 -import org.apidesign.html.boot.impl.FnContext;
   41.70 +import org.netbeans.html.boot.impl.FnContext;
   41.71  
   41.72  /** Represents single JavaScript function that can be invoked. 
   41.73   * Created via {@link Presenter#defineFn(java.lang.String, java.lang.String...)}.
    42.1 --- a/boot/src/main/java/org/apidesign/html/boot/spi/package.html	Thu Dec 19 17:11:01 2013 +0100
    42.2 +++ b/boot/src/main/java/org/apidesign/html/boot/spi/package.html	Tue Jan 07 08:21:57 2014 +0100
    42.3 @@ -1,23 +1,45 @@
    42.4  <!--
    42.5  
    42.6 -    HTML via Java(tm) Language Bindings
    42.7 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    42.8 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    42.9  
   42.10 -    This program is free software: you can redistribute it and/or modify
   42.11 -    it under the terms of the GNU General Public License as published by
   42.12 -    the Free Software Foundation, version 2 of the License.
   42.13 +    Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   42.14  
   42.15 -    This program is distributed in the hope that it will be useful,
   42.16 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   42.17 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   42.18 -    GNU General Public License for more details. apidesign.org
   42.19 -    designates this particular file as subject to the
   42.20 -    "Classpath" exception as provided by apidesign.org
   42.21 -    in the License file that accompanied this code.
   42.22 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   42.23 +    Other names may be trademarks of their respective owners.
   42.24  
   42.25 -    You should have received a copy of the GNU General Public License
   42.26 -    along with this program. Look for COPYING file in the top folder.
   42.27 -    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   42.28 +    The contents of this file are subject to the terms of either the GNU
   42.29 +    General Public License Version 2 only ("GPL") or the Common
   42.30 +    Development and Distribution License("CDDL") (collectively, the
   42.31 +    "License"). You may not use this file except in compliance with the
   42.32 +    License. You can obtain a copy of the License at
   42.33 +    http://www.netbeans.org/cddl-gplv2.html
   42.34 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   42.35 +    specific language governing permissions and limitations under the
   42.36 +    License.  When distributing the software, include this License Header
   42.37 +    Notice in each file and include the License file at
   42.38 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   42.39 +    particular file as subject to the "Classpath" exception as provided
   42.40 +    by Oracle in the GPL Version 2 section of the License file that
   42.41 +    accompanied this code. If applicable, add the following below the
   42.42 +    License Header, with the fields enclosed by brackets [] replaced by
   42.43 +    your own identifying information:
   42.44 +    "Portions Copyrighted [year] [name of copyright owner]"
   42.45 +
   42.46 +    Contributor(s):
   42.47 +
   42.48 +    The Original Software is NetBeans. The Initial Developer of the Original
   42.49 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   42.50 +
   42.51 +    If you wish your version of this file to be governed by only the CDDL
   42.52 +    or only the GPL Version 2, indicate your decision by adding
   42.53 +    "[Contributor] elects to include this software in this distribution
   42.54 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
   42.55 +    single choice of license, a recipient has the option to distribute
   42.56 +    your version of this file under either the CDDL, the GPL Version 2 or
   42.57 +    to extend the choice of license to its licensees as provided above.
   42.58 +    However, if you add GPL Version 2 code and therefore, elected the GPL
   42.59 +    Version 2 license, then the option applies only if the new code is
   42.60 +    made subject to such option by the copyright holder.
   42.61  
   42.62  -->
   42.63  <!DOCTYPE html>
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/FindResources.java	Tue Jan 07 08:21:57 2014 +0100
    43.3 @@ -0,0 +1,56 @@
    43.4 +/**
    43.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    43.6 + *
    43.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    43.8 + *
    43.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   43.10 + * Other names may be trademarks of their respective owners.
   43.11 + *
   43.12 + * The contents of this file are subject to the terms of either the GNU
   43.13 + * General Public License Version 2 only ("GPL") or the Common
   43.14 + * Development and Distribution License("CDDL") (collectively, the
   43.15 + * "License"). You may not use this file except in compliance with the
   43.16 + * License. You can obtain a copy of the License at
   43.17 + * http://www.netbeans.org/cddl-gplv2.html
   43.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   43.19 + * specific language governing permissions and limitations under the
   43.20 + * License.  When distributing the software, include this License Header
   43.21 + * Notice in each file and include the License file at
   43.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   43.23 + * particular file as subject to the "Classpath" exception as provided
   43.24 + * by Oracle in the GPL Version 2 section of the License file that
   43.25 + * accompanied this code. If applicable, add the following below the
   43.26 + * License Header, with the fields enclosed by brackets [] replaced by
   43.27 + * your own identifying information:
   43.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   43.29 + *
   43.30 + * Contributor(s):
   43.31 + *
   43.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   43.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   43.34 + *
   43.35 + * If you wish your version of this file to be governed by only the CDDL
   43.36 + * or only the GPL Version 2, indicate your decision by adding
   43.37 + * "[Contributor] elects to include this software in this distribution
   43.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   43.39 + * single choice of license, a recipient has the option to distribute
   43.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   43.41 + * to extend the choice of license to its licensees as provided above.
   43.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   43.43 + * Version 2 license, then the option applies only if the new code is
   43.44 + * made subject to such option by the copyright holder.
   43.45 + */
   43.46 +package org.netbeans.html.boot.impl;
   43.47 +
   43.48 +import java.net.URL;
   43.49 +import java.util.Collection;
   43.50 +
   43.51 +/**
   43.52 + *
   43.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   43.54 + */
   43.55 +public interface FindResources {
   43.56 +
   43.57 +    public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough);
   43.58 +    
   43.59 +}
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/FnContext.java	Tue Jan 07 08:21:57 2014 +0100
    44.3 @@ -0,0 +1,98 @@
    44.4 +/**
    44.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    44.6 + *
    44.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    44.8 + *
    44.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   44.10 + * Other names may be trademarks of their respective owners.
   44.11 + *
   44.12 + * The contents of this file are subject to the terms of either the GNU
   44.13 + * General Public License Version 2 only ("GPL") or the Common
   44.14 + * Development and Distribution License("CDDL") (collectively, the
   44.15 + * "License"). You may not use this file except in compliance with the
   44.16 + * License. You can obtain a copy of the License at
   44.17 + * http://www.netbeans.org/cddl-gplv2.html
   44.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   44.19 + * specific language governing permissions and limitations under the
   44.20 + * License.  When distributing the software, include this License Header
   44.21 + * Notice in each file and include the License file at
   44.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   44.23 + * particular file as subject to the "Classpath" exception as provided
   44.24 + * by Oracle in the GPL Version 2 section of the License file that
   44.25 + * accompanied this code. If applicable, add the following below the
   44.26 + * License Header, with the fields enclosed by brackets [] replaced by
   44.27 + * your own identifying information:
   44.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   44.29 + *
   44.30 + * Contributor(s):
   44.31 + *
   44.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   44.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   44.34 + *
   44.35 + * If you wish your version of this file to be governed by only the CDDL
   44.36 + * or only the GPL Version 2, indicate your decision by adding
   44.37 + * "[Contributor] elects to include this software in this distribution
   44.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   44.39 + * single choice of license, a recipient has the option to distribute
   44.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   44.41 + * to extend the choice of license to its licensees as provided above.
   44.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   44.43 + * Version 2 license, then the option applies only if the new code is
   44.44 + * made subject to such option by the copyright holder.
   44.45 + */
   44.46 +package org.netbeans.html.boot.impl;
   44.47 +
   44.48 +import java.io.Closeable;
   44.49 +import java.io.IOException;
   44.50 +import java.util.logging.Logger;
   44.51 +import org.apidesign.html.boot.spi.Fn;
   44.52 +
   44.53 +/**
   44.54 + *
   44.55 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   44.56 + */
   44.57 +public final class FnContext implements Closeable {
   44.58 +    private static final Logger LOG = Logger.getLogger(FnContext.class.getName());
   44.59 +
   44.60 +    private Object prev;
   44.61 +    private FnContext(Fn.Presenter p) {
   44.62 +        this.prev = p;
   44.63 +    }
   44.64 +
   44.65 +    @Override
   44.66 +    public void close() throws IOException {
   44.67 +        if (prev != this) {
   44.68 +            currentPresenter((Fn.Presenter)prev);
   44.69 +            prev = this;
   44.70 +        }
   44.71 +    }
   44.72 +/*
   44.73 +    @Override
   44.74 +    protected void finalize() throws Throwable {
   44.75 +        if (prev != null) {
   44.76 +            LOG.warning("Unclosed context!");
   44.77 +        }
   44.78 +    }
   44.79 +*/
   44.80 +    public static Closeable activate(Fn.Presenter newP) {
   44.81 +        return new FnContext(currentPresenter(newP));
   44.82 +    }
   44.83 +    
   44.84 +    
   44.85 +    private static final ThreadLocal<Fn.Presenter> CURRENT = new ThreadLocal<Fn.Presenter>();
   44.86 +
   44.87 +    public static Fn.Presenter currentPresenter(Fn.Presenter p) {
   44.88 +        Fn.Presenter prev = CURRENT.get();
   44.89 +        CURRENT.set(p);
   44.90 +        return prev;
   44.91 +    }
   44.92 +
   44.93 +    public static Fn.Presenter currentPresenter(boolean canReturnNull) {
   44.94 +        Fn.Presenter p = CURRENT.get();
   44.95 +        if (p == null && !canReturnNull) {
   44.96 +            throw new IllegalStateException("No current WebView context around!");
   44.97 +        }
   44.98 +        return p;
   44.99 +    }
  44.100 +    
  44.101 +}
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/FnUtils.java	Tue Jan 07 08:21:57 2014 +0100
    45.3 @@ -0,0 +1,618 @@
    45.4 +/**
    45.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    45.6 + *
    45.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    45.8 + *
    45.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   45.10 + * Other names may be trademarks of their respective owners.
   45.11 + *
   45.12 + * The contents of this file are subject to the terms of either the GNU
   45.13 + * General Public License Version 2 only ("GPL") or the Common
   45.14 + * Development and Distribution License("CDDL") (collectively, the
   45.15 + * "License"). You may not use this file except in compliance with the
   45.16 + * License. You can obtain a copy of the License at
   45.17 + * http://www.netbeans.org/cddl-gplv2.html
   45.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   45.19 + * specific language governing permissions and limitations under the
   45.20 + * License.  When distributing the software, include this License Header
   45.21 + * Notice in each file and include the License file at
   45.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   45.23 + * particular file as subject to the "Classpath" exception as provided
   45.24 + * by Oracle in the GPL Version 2 section of the License file that
   45.25 + * accompanied this code. If applicable, add the following below the
   45.26 + * License Header, with the fields enclosed by brackets [] replaced by
   45.27 + * your own identifying information:
   45.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   45.29 + *
   45.30 + * Contributor(s):
   45.31 + *
   45.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   45.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   45.34 + *
   45.35 + * If you wish your version of this file to be governed by only the CDDL
   45.36 + * or only the GPL Version 2, indicate your decision by adding
   45.37 + * "[Contributor] elects to include this software in this distribution
   45.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   45.39 + * single choice of license, a recipient has the option to distribute
   45.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   45.41 + * to extend the choice of license to its licensees as provided above.
   45.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   45.43 + * Version 2 license, then the option applies only if the new code is
   45.44 + * made subject to such option by the copyright holder.
   45.45 + */
   45.46 +package org.netbeans.html.boot.impl;
   45.47 +
   45.48 +import java.io.Closeable;
   45.49 +import java.io.IOException;
   45.50 +import java.io.InputStream;
   45.51 +import java.io.InputStreamReader;
   45.52 +import java.io.Reader;
   45.53 +import java.net.URL;
   45.54 +import java.util.ArrayList;
   45.55 +import java.util.Collections;
   45.56 +import java.util.Enumeration;
   45.57 +import java.util.List;
   45.58 +import java.util.concurrent.Callable;
   45.59 +import org.apidesign.html.boot.spi.Fn;
   45.60 +import org.objectweb.asm.AnnotationVisitor;
   45.61 +import org.objectweb.asm.ClassReader;
   45.62 +import org.objectweb.asm.ClassVisitor;
   45.63 +import org.objectweb.asm.ClassWriter;
   45.64 +import org.objectweb.asm.Label;
   45.65 +import org.objectweb.asm.MethodVisitor;
   45.66 +import org.objectweb.asm.Opcodes;
   45.67 +import org.objectweb.asm.Type;
   45.68 +import org.objectweb.asm.signature.SignatureReader;
   45.69 +import org.objectweb.asm.signature.SignatureVisitor;
   45.70 +import org.objectweb.asm.signature.SignatureWriter;
   45.71 +
   45.72 +/**
   45.73 + *
   45.74 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   45.75 + */
   45.76 +public final class FnUtils implements Fn.Presenter {
   45.77 +    
   45.78 +    private FnUtils() {
   45.79 +    }
   45.80 +    
   45.81 +    /** Seeks for {@link JavaScriptBody} and {@link JavaScriptResource} annotations
   45.82 +     * in the bytecode and converts them into real code. Used by Maven plugin
   45.83 +     * postprocessing classes.
   45.84 +     * 
   45.85 +     * @param bytecode the original bytecode with javascript specific annotations
   45.86 +     * @param loader the loader to load resources (scripts and classes) when needed
   45.87 +     * @return the transformed bytecode
   45.88 +     * @since 0.7
   45.89 +     */
   45.90 +    public static byte[] transform(byte[] bytecode, ClassLoader loader) {
   45.91 +        ClassReader cr = new ClassReader(bytecode) {
   45.92 +            // to allow us to compile with -profile compact1 on 
   45.93 +            // JDK8 while processing the class as JDK7, the highest
   45.94 +            // class format asm 4.1 understands to
   45.95 +            @Override
   45.96 +            public short readShort(int index) {
   45.97 +                short s = super.readShort(index);
   45.98 +                if (index == 6 && s > Opcodes.V1_7) {
   45.99 +                    return Opcodes.V1_7;
  45.100 +                }
  45.101 +                return s;
  45.102 +            }
  45.103 +        };
  45.104 +        FindInClass tst = new FindInClass(loader, null);
  45.105 +        cr.accept(tst, 0);
  45.106 +        if (tst.found > 0) {
  45.107 +            ClassWriter w = new ClassWriterEx(loader, cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
  45.108 +            FindInClass fic = new FindInClass(loader, w);
  45.109 +            cr.accept(fic, 0);
  45.110 +            bytecode = w.toByteArray();
  45.111 +        }
  45.112 +        return bytecode;
  45.113 +    }
  45.114 +    
  45.115 +    public static boolean isJavaScriptCapable(ClassLoader l) {
  45.116 +        if (l instanceof JsClassLoader) {
  45.117 +            return true;
  45.118 +        }
  45.119 +        Class<?> clazz;
  45.120 +        Closeable c = Fn.activate(new FnUtils());
  45.121 +        try {
  45.122 +            try {
  45.123 +                clazz = Class.forName(Test.class.getName(), true, l);
  45.124 +            } catch (ClassNotFoundException ex) {
  45.125 +                clazz = Test.class;
  45.126 +            }
  45.127 +            final Object is = ((Callable<?>)clazz.newInstance()).call();
  45.128 +            return Boolean.TRUE.equals(is);
  45.129 +        } catch (Exception ex) {
  45.130 +            return false;
  45.131 +        } finally {
  45.132 +            try {
  45.133 +                c.close();
  45.134 +            } catch (IOException ex) {
  45.135 +                throw new IllegalStateException(ex);
  45.136 +            }
  45.137 +        }
  45.138 +    }
  45.139 +    
  45.140 +    public static boolean isValid(Fn fn) {
  45.141 +        return fn != null && fn.isValid();
  45.142 +    }
  45.143 +
  45.144 +    public static ClassLoader newLoader(final FindResources f, final Fn.Presenter d, ClassLoader parent) {
  45.145 +        return new JsClassLoader(parent) {
  45.146 +            @Override
  45.147 +            protected URL findResource(String name) {
  45.148 +                List<URL> l = res(name, true);
  45.149 +                return l.isEmpty() ? null : l.get(0);
  45.150 +            }
  45.151 +            
  45.152 +            @Override
  45.153 +            protected Enumeration<URL> findResources(String name) {
  45.154 +                return Collections.enumeration(res(name, false));
  45.155 +            }
  45.156 +            
  45.157 +            private List<URL> res(String name, boolean oneIsEnough) {
  45.158 +                List<URL> l = new ArrayList<URL>();
  45.159 +                f.findResources(name, l, oneIsEnough);
  45.160 +                return l;
  45.161 +            }
  45.162 +            
  45.163 +            @Override
  45.164 +            protected Fn defineFn(String code, String... names) {
  45.165 +                return d.defineFn(code, names);
  45.166 +            }
  45.167 +
  45.168 +            @Override
  45.169 +            protected void loadScript(Reader code) throws Exception {
  45.170 +                d.loadScript(code);
  45.171 +            }
  45.172 +        };
  45.173 +    }
  45.174 +
  45.175 +    static String callback(final String body) {
  45.176 +        return new JsCallback() {
  45.177 +            @Override
  45.178 +            protected CharSequence callMethod(
  45.179 +                String ident, String fqn, String method, String params
  45.180 +            ) {
  45.181 +                StringBuilder sb = new StringBuilder();
  45.182 +                sb.append("vm.").append(mangle(fqn, method, params));
  45.183 +                sb.append("(");
  45.184 +                if (ident != null) {
  45.185 +                    sb.append(ident);
  45.186 +                }
  45.187 +                return sb;
  45.188 +            }
  45.189 +
  45.190 +        }.parse(body);
  45.191 +    }
  45.192 +
  45.193 +    static void loadScript(ClassLoader jcl, String resource) {
  45.194 +        final InputStream script = jcl.getResourceAsStream(resource);
  45.195 +        if (script == null) {
  45.196 +            throw new NullPointerException("Can't find " + resource);
  45.197 +        }
  45.198 +        try {
  45.199 +            Reader isr = null;
  45.200 +            try {
  45.201 +                isr = new InputStreamReader(script, "UTF-8");
  45.202 +                FnContext.currentPresenter(false).loadScript(isr);
  45.203 +            } finally {
  45.204 +                if (isr != null) {
  45.205 +                    isr.close();
  45.206 +                }
  45.207 +            }
  45.208 +        } catch (Exception ex) {
  45.209 +            throw new IllegalStateException("Can't execute " + resource, ex);
  45.210 +        } 
  45.211 +    }
  45.212 +
  45.213 +    @Override
  45.214 +    public Fn defineFn(String code, String... names) {
  45.215 +        return new TrueFn();
  45.216 +    }
  45.217 +
  45.218 +    @Override
  45.219 +    public void displayPage(URL page, Runnable onPageLoad) {
  45.220 +    }
  45.221 +
  45.222 +    @Override
  45.223 +    public void loadScript(Reader code) throws Exception {
  45.224 +    }
  45.225 +    
  45.226 +    private static final class FindInClass extends ClassVisitor {
  45.227 +        private String name;
  45.228 +        private int found;
  45.229 +        private ClassLoader loader;
  45.230 +        private String resource;
  45.231 +
  45.232 +        public FindInClass(ClassLoader l, ClassVisitor cv) {
  45.233 +            super(Opcodes.ASM4, cv);
  45.234 +            this.loader = l;
  45.235 +        }
  45.236 +
  45.237 +        @Override
  45.238 +        public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
  45.239 +            this.name = name;
  45.240 +            super.visit(version, access, name, signature, superName, interfaces);
  45.241 +        }
  45.242 +
  45.243 +        @Override
  45.244 +        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
  45.245 +            if ("Lnet/java/html/js/JavaScriptResource;".equals(desc)) {
  45.246 +                return new LoadResource();
  45.247 +            }
  45.248 +            return super.visitAnnotation(desc, visible);
  45.249 +        }
  45.250 +
  45.251 +        @Override
  45.252 +        public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
  45.253 +            return new FindInMethod(access, name, desc,
  45.254 +                    super.visitMethod(access & (~Opcodes.ACC_NATIVE), name, desc, signature, exceptions)
  45.255 +            );
  45.256 +        }
  45.257 +
  45.258 +        private final class FindInMethod extends MethodVisitor {
  45.259 +
  45.260 +            private final String name;
  45.261 +            private final String desc;
  45.262 +            private final int access;
  45.263 +            private List<String> args;
  45.264 +            private String body;
  45.265 +            private boolean bodyGenerated;
  45.266 +
  45.267 +            public FindInMethod(int access, String name, String desc, MethodVisitor mv) {
  45.268 +                super(Opcodes.ASM4, mv);
  45.269 +                this.access = access;
  45.270 +                this.name = name;
  45.271 +                this.desc = desc;
  45.272 +            }
  45.273 +
  45.274 +            @Override
  45.275 +            public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
  45.276 +                if ("Lnet/java/html/js/JavaScriptBody;".equals(desc) // NOI18N
  45.277 +                        || "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;".equals(desc) // NOI18N
  45.278 +                        ) {
  45.279 +                    found++;
  45.280 +                    return new FindInAnno();
  45.281 +                }
  45.282 +                return super.visitAnnotation(desc, visible);
  45.283 +            }
  45.284 +
  45.285 +            private void generateJSBody(List<String> args, String body) {
  45.286 +                this.args = args;
  45.287 +                this.body = body;
  45.288 +            }
  45.289 +
  45.290 +            @Override
  45.291 +            public void visitCode() {
  45.292 +                if (body == null) {
  45.293 +                    return;
  45.294 +                }
  45.295 +                generateBody();
  45.296 +            }
  45.297 +
  45.298 +            private boolean generateBody() {
  45.299 +                if (bodyGenerated) {
  45.300 +                    return false;
  45.301 +                }
  45.302 +                bodyGenerated = true;
  45.303 +
  45.304 +                super.visitFieldInsn(
  45.305 +                        Opcodes.GETSTATIC, FindInClass.this.name,
  45.306 +                        "$$fn$$" + name + "_" + found,
  45.307 +                        "Lorg/apidesign/html/boot/spi/Fn;"
  45.308 +                );
  45.309 +                super.visitInsn(Opcodes.DUP);
  45.310 +                super.visitMethodInsn(
  45.311 +                        Opcodes.INVOKESTATIC,
  45.312 +                        "org/apidesign/html/boot/spi/Fn", "isValid",
  45.313 +                        "(Lorg/apidesign/html/boot/spi/Fn;)Z"
  45.314 +                );
  45.315 +                Label ifNotNull = new Label();
  45.316 +                super.visitJumpInsn(Opcodes.IFNE, ifNotNull);
  45.317 +
  45.318 +                // init Fn
  45.319 +                super.visitInsn(Opcodes.POP);
  45.320 +                super.visitLdcInsn(Type.getObjectType(FindInClass.this.name));
  45.321 +                super.visitLdcInsn(body);
  45.322 +                super.visitIntInsn(Opcodes.SIPUSH, args.size());
  45.323 +                super.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/String");
  45.324 +                boolean needsVM = false;
  45.325 +                for (int i = 0; i < args.size(); i++) {
  45.326 +                    assert !needsVM;
  45.327 +                    String argName = args.get(i);
  45.328 +                    needsVM = "vm".equals(argName);
  45.329 +                    super.visitInsn(Opcodes.DUP);
  45.330 +                    super.visitIntInsn(Opcodes.BIPUSH, i);
  45.331 +                    super.visitLdcInsn(argName);
  45.332 +                    super.visitInsn(Opcodes.AASTORE);
  45.333 +                }
  45.334 +                super.visitMethodInsn(Opcodes.INVOKESTATIC,
  45.335 +                        "org/apidesign/html/boot/spi/Fn", "define",
  45.336 +                        "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/String;)Lorg/apidesign/html/boot/spi/Fn;"
  45.337 +                );
  45.338 +                if (resource != null) {
  45.339 +                    super.visitLdcInsn(Type.getObjectType(FindInClass.this.name));
  45.340 +                    super.visitLdcInsn(resource);
  45.341 +                    super.visitMethodInsn(Opcodes.INVOKESTATIC,
  45.342 +                            "org/apidesign/html/boot/spi/Fn", "preload",
  45.343 +                            "(Lorg/apidesign/html/boot/spi/Fn;Ljava/lang/Class;Ljava/lang/String;)Lorg/apidesign/html/boot/spi/Fn;"
  45.344 +                    );
  45.345 +                }
  45.346 +                super.visitInsn(Opcodes.DUP);
  45.347 +                super.visitFieldInsn(
  45.348 +                        Opcodes.PUTSTATIC, FindInClass.this.name,
  45.349 +                        "$$fn$$" + name + "_" + found,
  45.350 +                        "Lorg/apidesign/html/boot/spi/Fn;"
  45.351 +                );
  45.352 +                // end of Fn init
  45.353 +
  45.354 +                super.visitLabel(ifNotNull);
  45.355 +
  45.356 +                final int offset;
  45.357 +                if ((access & Opcodes.ACC_STATIC) == 0) {
  45.358 +                    offset = 1;
  45.359 +                    super.visitIntInsn(Opcodes.ALOAD, 0);
  45.360 +                } else {
  45.361 +                    offset = 0;
  45.362 +                    super.visitInsn(Opcodes.ACONST_NULL);
  45.363 +                }
  45.364 +
  45.365 +                super.visitIntInsn(Opcodes.SIPUSH, args.size());
  45.366 +                super.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
  45.367 +
  45.368 +                class SV extends SignatureVisitor {
  45.369 +
  45.370 +                    private boolean nowReturn;
  45.371 +                    private Type returnType;
  45.372 +                    private int index;
  45.373 +                    private int loadIndex = offset;
  45.374 +
  45.375 +                    public SV() {
  45.376 +                        super(Opcodes.ASM4);
  45.377 +                    }
  45.378 +
  45.379 +                    @Override
  45.380 +                    public void visitBaseType(char descriptor) {
  45.381 +                        final Type t = Type.getType("" + descriptor);
  45.382 +                        if (nowReturn) {
  45.383 +                            returnType = t;
  45.384 +                            return;
  45.385 +                        }
  45.386 +                        FindInMethod.super.visitInsn(Opcodes.DUP);
  45.387 +                        FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, index++);
  45.388 +                        FindInMethod.super.visitVarInsn(t.getOpcode(Opcodes.ILOAD), loadIndex++);
  45.389 +                        String factory;
  45.390 +                        switch (descriptor) {
  45.391 +                            case 'I':
  45.392 +                                factory = "java/lang/Integer";
  45.393 +                                break;
  45.394 +                            case 'J':
  45.395 +                                factory = "java/lang/Long";
  45.396 +                                loadIndex++;
  45.397 +                                break;
  45.398 +                            case 'S':
  45.399 +                                factory = "java/lang/Short";
  45.400 +                                break;
  45.401 +                            case 'F':
  45.402 +                                factory = "java/lang/Float";
  45.403 +                                break;
  45.404 +                            case 'D':
  45.405 +                                factory = "java/lang/Double";
  45.406 +                                loadIndex++;
  45.407 +                                break;
  45.408 +                            case 'Z':
  45.409 +                                factory = "java/lang/Boolean";
  45.410 +                                break;
  45.411 +                            case 'C':
  45.412 +                                factory = "java/lang/Character";
  45.413 +                                break;
  45.414 +                            case 'B':
  45.415 +                                factory = "java/lang/Byte";
  45.416 +                                break;
  45.417 +                            default:
  45.418 +                                throw new IllegalStateException(t.toString());
  45.419 +                        }
  45.420 +                        FindInMethod.super.visitMethodInsn(Opcodes.INVOKESTATIC,
  45.421 +                                factory, "valueOf", "(" + descriptor + ")L" + factory + ";"
  45.422 +                        );
  45.423 +                        FindInMethod.super.visitInsn(Opcodes.AASTORE);
  45.424 +                    }
  45.425 +
  45.426 +                    @Override
  45.427 +                    public SignatureVisitor visitArrayType() {
  45.428 +                        if (nowReturn) {
  45.429 +                            throw new IllegalStateException("Not supported yet");
  45.430 +                        }
  45.431 +                        loadObject();
  45.432 +                        return new SignatureWriter();
  45.433 +                    }
  45.434 +
  45.435 +                    @Override
  45.436 +                    public void visitClassType(String name) {
  45.437 +                        if (nowReturn) {
  45.438 +                            returnType = Type.getObjectType(name);
  45.439 +                            return;
  45.440 +                        }
  45.441 +                        loadObject();
  45.442 +                    }
  45.443 +
  45.444 +                    @Override
  45.445 +                    public SignatureVisitor visitReturnType() {
  45.446 +                        nowReturn = true;
  45.447 +                        return this;
  45.448 +                    }
  45.449 +
  45.450 +                    private void loadObject() {
  45.451 +                        FindInMethod.super.visitInsn(Opcodes.DUP);
  45.452 +                        FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, index++);
  45.453 +                        FindInMethod.super.visitVarInsn(Opcodes.ALOAD, loadIndex++);
  45.454 +                        FindInMethod.super.visitInsn(Opcodes.AASTORE);
  45.455 +                    }
  45.456 +
  45.457 +                }
  45.458 +                SV sv = new SV();
  45.459 +                SignatureReader sr = new SignatureReader(desc);
  45.460 +                sr.accept(sv);
  45.461 +
  45.462 +                if (needsVM) {
  45.463 +                    FindInMethod.super.visitInsn(Opcodes.DUP);
  45.464 +                    FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, sv.index);
  45.465 +                    int lastSlash = FindInClass.this.name.lastIndexOf('/');
  45.466 +                    String jsCallbacks = FindInClass.this.name.substring(0, lastSlash + 1) + "$JsCallbacks$";
  45.467 +                    FindInMethod.super.visitFieldInsn(Opcodes.GETSTATIC, jsCallbacks, "VM", "L" + jsCallbacks + ";");
  45.468 +                    FindInMethod.super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, jsCallbacks, "current", "()L" + jsCallbacks + ";");
  45.469 +                    FindInMethod.super.visitInsn(Opcodes.AASTORE);
  45.470 +                }
  45.471 +
  45.472 +                super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
  45.473 +                        "org/apidesign/html/boot/spi/Fn", "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"
  45.474 +                );
  45.475 +                switch (sv.returnType.getSort()) {
  45.476 +                    case Type.VOID:
  45.477 +                        super.visitInsn(Opcodes.RETURN);
  45.478 +                        break;
  45.479 +                    case Type.ARRAY:
  45.480 +                    case Type.OBJECT:
  45.481 +                        super.visitTypeInsn(Opcodes.CHECKCAST, sv.returnType.getInternalName());
  45.482 +                        super.visitInsn(Opcodes.ARETURN);
  45.483 +                        break;
  45.484 +                    case Type.BOOLEAN:
  45.485 +                        super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Boolean");
  45.486 +                        super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
  45.487 +                                "java/lang/Boolean", "booleanValue", "()Z"
  45.488 +                        );
  45.489 +                        super.visitInsn(Opcodes.IRETURN);
  45.490 +                        break;
  45.491 +                    default:
  45.492 +                        super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Number");
  45.493 +                        super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
  45.494 +                                "java/lang/Number", sv.returnType.getClassName() + "Value", "()" + sv.returnType.getDescriptor()
  45.495 +                        );
  45.496 +                        super.visitInsn(sv.returnType.getOpcode(Opcodes.IRETURN));
  45.497 +                }
  45.498 +                return true;
  45.499 +            }
  45.500 +
  45.501 +            @Override
  45.502 +            public void visitEnd() {
  45.503 +                super.visitEnd();
  45.504 +                if (body != null) {
  45.505 +                    if (generateBody()) {
  45.506 +                        // native method
  45.507 +                        super.visitMaxs(1, 0);
  45.508 +                    }
  45.509 +                    FindInClass.this.visitField(
  45.510 +                            Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
  45.511 +                            "$$fn$$" + name + "_" + found,
  45.512 +                            "Lorg/apidesign/html/boot/spi/Fn;",
  45.513 +                            null, null
  45.514 +                    );
  45.515 +                }
  45.516 +            }
  45.517 +
  45.518 +            private final class FindInAnno extends AnnotationVisitor {
  45.519 +
  45.520 +                private List<String> args = new ArrayList<String>();
  45.521 +                private String body;
  45.522 +                private boolean javacall = false;
  45.523 +
  45.524 +                public FindInAnno() {
  45.525 +                    super(Opcodes.ASM4);
  45.526 +                }
  45.527 +
  45.528 +                @Override
  45.529 +                public void visit(String name, Object value) {
  45.530 +                    if (name == null) {
  45.531 +                        args.add((String) value);
  45.532 +                        return;
  45.533 +                    }
  45.534 +                    if (name.equals("javacall")) { // NOI18N
  45.535 +                        javacall = (Boolean) value;
  45.536 +                        return;
  45.537 +                    }
  45.538 +                    assert name.equals("body");
  45.539 +                    body = (String) value;
  45.540 +                }
  45.541 +
  45.542 +                @Override
  45.543 +                public AnnotationVisitor visitArray(String name) {
  45.544 +                    return this;
  45.545 +                }
  45.546 +
  45.547 +                @Override
  45.548 +                public void visitEnd() {
  45.549 +                    if (body != null) {
  45.550 +                        if (javacall) {
  45.551 +                            body = callback(body);
  45.552 +                            args.add("vm");
  45.553 +                        }
  45.554 +                        generateJSBody(args, body);
  45.555 +                    }
  45.556 +                }
  45.557 +            }
  45.558 +        }
  45.559 +
  45.560 +        private final class LoadResource extends AnnotationVisitor {
  45.561 +
  45.562 +            public LoadResource() {
  45.563 +                super(Opcodes.ASM4);
  45.564 +            }
  45.565 +
  45.566 +            @Override
  45.567 +            public void visit(String attrName, Object value) {
  45.568 +                String relPath = (String) value;
  45.569 +                if (relPath.startsWith("/")) {
  45.570 +                    resource = relPath;
  45.571 +                } else {
  45.572 +                    int last = name.lastIndexOf('/');
  45.573 +                    String fullPath = name.substring(0, last + 1) + relPath;
  45.574 +                    resource = fullPath;
  45.575 +                }
  45.576 +            }
  45.577 +        }
  45.578 +    }
  45.579 +
  45.580 +    private static class ClassWriterEx extends ClassWriter {
  45.581 +
  45.582 +        private ClassLoader loader;
  45.583 +
  45.584 +        public ClassWriterEx(ClassLoader l, ClassReader classReader, int flags) {
  45.585 +            super(classReader, flags);
  45.586 +            this.loader = l;
  45.587 +        }
  45.588 +
  45.589 +        @Override
  45.590 +        protected String getCommonSuperClass(final String type1, final String type2) {
  45.591 +            Class<?> c, d;
  45.592 +            try {
  45.593 +                c = Class.forName(type1.replace('/', '.'), false, loader);
  45.594 +                d = Class.forName(type2.replace('/', '.'), false, loader);
  45.595 +            } catch (Exception e) {
  45.596 +                throw new RuntimeException(e.toString());
  45.597 +            }
  45.598 +            if (c.isAssignableFrom(d)) {
  45.599 +                return type1;
  45.600 +            }
  45.601 +            if (d.isAssignableFrom(c)) {
  45.602 +                return type2;
  45.603 +            }
  45.604 +            if (c.isInterface() || d.isInterface()) {
  45.605 +                return "java/lang/Object";
  45.606 +            } else {
  45.607 +                do {
  45.608 +                    c = c.getSuperclass();
  45.609 +                } while (!c.isAssignableFrom(d));
  45.610 +                return c.getName().replace('.', '/');
  45.611 +            }
  45.612 +        }
  45.613 +    }
  45.614 +
  45.615 +    private static final class TrueFn extends Fn {
  45.616 +        @Override
  45.617 +        public Object invoke(Object thiz, Object... args) throws Exception {
  45.618 +            return Boolean.TRUE;
  45.619 +        }
  45.620 +    } // end of TrueFn
  45.621 +}
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/JavaScriptProcesor.java	Tue Jan 07 08:21:57 2014 +0100
    46.3 @@ -0,0 +1,369 @@
    46.4 +/**
    46.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    46.6 + *
    46.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    46.8 + *
    46.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   46.10 + * Other names may be trademarks of their respective owners.
   46.11 + *
   46.12 + * The contents of this file are subject to the terms of either the GNU
   46.13 + * General Public License Version 2 only ("GPL") or the Common
   46.14 + * Development and Distribution License("CDDL") (collectively, the
   46.15 + * "License"). You may not use this file except in compliance with the
   46.16 + * License. You can obtain a copy of the License at
   46.17 + * http://www.netbeans.org/cddl-gplv2.html
   46.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   46.19 + * specific language governing permissions and limitations under the
   46.20 + * License.  When distributing the software, include this License Header
   46.21 + * Notice in each file and include the License file at
   46.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   46.23 + * particular file as subject to the "Classpath" exception as provided
   46.24 + * by Oracle in the GPL Version 2 section of the License file that
   46.25 + * accompanied this code. If applicable, add the following below the
   46.26 + * License Header, with the fields enclosed by brackets [] replaced by
   46.27 + * your own identifying information:
   46.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   46.29 + *
   46.30 + * Contributor(s):
   46.31 + *
   46.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   46.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   46.34 + *
   46.35 + * If you wish your version of this file to be governed by only the CDDL
   46.36 + * or only the GPL Version 2, indicate your decision by adding
   46.37 + * "[Contributor] elects to include this software in this distribution
   46.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   46.39 + * single choice of license, a recipient has the option to distribute
   46.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   46.41 + * to extend the choice of license to its licensees as provided above.
   46.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   46.43 + * Version 2 license, then the option applies only if the new code is
   46.44 + * made subject to such option by the copyright holder.
   46.45 + */
   46.46 +package org.netbeans.html.boot.impl;
   46.47 +
   46.48 +import java.io.IOException;
   46.49 +import java.io.Writer;
   46.50 +import java.util.Collections;
   46.51 +import java.util.HashMap;
   46.52 +import java.util.HashSet;
   46.53 +import java.util.List;
   46.54 +import java.util.Map;
   46.55 +import java.util.Set;
   46.56 +import java.util.TreeMap;
   46.57 +import javax.annotation.processing.AbstractProcessor;
   46.58 +import javax.annotation.processing.Completion;
   46.59 +import javax.annotation.processing.Completions;
   46.60 +import javax.annotation.processing.Messager;
   46.61 +import javax.annotation.processing.Processor;
   46.62 +import javax.annotation.processing.RoundEnvironment;
   46.63 +import javax.lang.model.SourceVersion;
   46.64 +import javax.lang.model.element.AnnotationMirror;
   46.65 +import javax.lang.model.element.Element;
   46.66 +import javax.lang.model.element.ElementKind;
   46.67 +import javax.lang.model.element.ExecutableElement;
   46.68 +import javax.lang.model.element.Modifier;
   46.69 +import javax.lang.model.element.PackageElement;
   46.70 +import javax.lang.model.element.TypeElement;
   46.71 +import javax.lang.model.element.VariableElement;
   46.72 +import javax.lang.model.type.ArrayType;
   46.73 +import javax.lang.model.type.ExecutableType;
   46.74 +import javax.lang.model.type.TypeKind;
   46.75 +import javax.lang.model.type.TypeMirror;
   46.76 +import javax.tools.Diagnostic;
   46.77 +import javax.tools.FileObject;
   46.78 +import javax.tools.StandardLocation;
   46.79 +import net.java.html.js.JavaScriptBody;
   46.80 +import net.java.html.js.JavaScriptResource;
   46.81 +import org.openide.util.lookup.ServiceProvider;
   46.82 +
   46.83 +/**
   46.84 + *
   46.85 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   46.86 + */
   46.87 +@ServiceProvider(service = Processor.class)
   46.88 +public final class JavaScriptProcesor extends AbstractProcessor {
   46.89 +    private final Map<String,Map<String,ExecutableElement>> javacalls = 
   46.90 +        new HashMap<String,Map<String,ExecutableElement>>();
   46.91 +    
   46.92 +    @Override
   46.93 +    public Set<String> getSupportedAnnotationTypes() {
   46.94 +        Set<String> set = new HashSet<String>();
   46.95 +        set.add(JavaScriptBody.class.getName());
   46.96 +        set.add(JavaScriptResource.class.getName());
   46.97 +        return set;
   46.98 +    }
   46.99 +    
  46.100 +    @Override
  46.101 +    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
  46.102 +        final Messager msg = processingEnv.getMessager();
  46.103 +        for (Element e : roundEnv.getElementsAnnotatedWith(JavaScriptBody.class)) {
  46.104 +            if (e.getKind() != ElementKind.METHOD && e.getKind() != ElementKind.CONSTRUCTOR) {
  46.105 +                continue;
  46.106 +            }
  46.107 +            ExecutableElement ee = (ExecutableElement)e;
  46.108 +            List<? extends VariableElement> params = ee.getParameters();
  46.109 +            
  46.110 +            JavaScriptBody jsb = e.getAnnotation(JavaScriptBody.class);
  46.111 +            if (jsb == null) {
  46.112 +                continue;
  46.113 +            }
  46.114 +            String[] arr = jsb.args();
  46.115 +            if (params.size() != arr.length) {
  46.116 +                msg.printMessage(Diagnostic.Kind.ERROR, "Number of args arguments does not match real arguments!", e);
  46.117 +            }
  46.118 +            if (!jsb.javacall() && jsb.body().contains(".@")) {
  46.119 +                msg.printMessage(Diagnostic.Kind.WARNING, "Usage of .@ usually requires javacall=true", e);
  46.120 +            }
  46.121 +            if (jsb.javacall()) {
  46.122 +                JsCallback verify = new VerifyCallback(e);
  46.123 +                try {
  46.124 +                    verify.parse(jsb.body());
  46.125 +                } catch (IllegalStateException ex) {
  46.126 +                    msg.printMessage(Diagnostic.Kind.ERROR, ex.getLocalizedMessage(), e);
  46.127 +                }
  46.128 +            }
  46.129 +        }
  46.130 +        for (Element e : roundEnv.getElementsAnnotatedWith(JavaScriptResource.class)) {
  46.131 +            JavaScriptResource r = e.getAnnotation(JavaScriptResource.class);
  46.132 +            if (r == null) {
  46.133 +                continue;
  46.134 +            }
  46.135 +            final String res;
  46.136 +            if (r.value().startsWith("/")) {
  46.137 +                res = r.value();
  46.138 +            } else {
  46.139 +                res = findPkg(e).replace('.', '/') + "/" + r.value();
  46.140 +            }
  46.141 +            
  46.142 +            try {
  46.143 +                FileObject os = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", res);
  46.144 +                os.openInputStream().close();
  46.145 +            } catch (IOException ex1) {
  46.146 +                try {
  46.147 +                    FileObject os2 = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", res);
  46.148 +                    os2.openInputStream().close();
  46.149 +                } catch (IOException ex2) {
  46.150 +                    msg.printMessage(Diagnostic.Kind.ERROR, "Cannot find " + res + " in " + res + " package", e);
  46.151 +                }
  46.152 +            }
  46.153 +        }
  46.154 +
  46.155 +        if (roundEnv.processingOver()) {
  46.156 +            generateCallbackClass(javacalls);
  46.157 +            javacalls.clear();
  46.158 +        }
  46.159 +        return true;
  46.160 +    }
  46.161 +
  46.162 +    @Override
  46.163 +    public Iterable<? extends Completion> getCompletions(Element e, 
  46.164 +        AnnotationMirror annotation, ExecutableElement member, String userText
  46.165 +    ) {
  46.166 +        StringBuilder sb = new StringBuilder();
  46.167 +        if (e.getKind() == ElementKind.METHOD && member.getSimpleName().contentEquals("args")) {
  46.168 +            ExecutableElement ee = (ExecutableElement) e;
  46.169 +            String sep = "";
  46.170 +            sb.append("{ ");
  46.171 +            for (VariableElement ve : ee.getParameters()) {
  46.172 +                sb.append(sep).append('"').append(ve.getSimpleName())
  46.173 +                    .append('"');
  46.174 +                sep = ", ";
  46.175 +            }
  46.176 +            sb.append(" }");
  46.177 +            return Collections.nCopies(1, Completions.of(sb.toString()));
  46.178 +        }
  46.179 +        return null;
  46.180 +    }
  46.181 +
  46.182 +    private class VerifyCallback extends JsCallback {
  46.183 +        private final Element e;
  46.184 +        public VerifyCallback(Element e) {
  46.185 +            this.e = e;
  46.186 +        }
  46.187 +
  46.188 +        @Override
  46.189 +        protected CharSequence callMethod(String ident, String fqn, String method, String params) {
  46.190 +            final TypeElement type = processingEnv.getElementUtils().getTypeElement(fqn);
  46.191 +            if (type == null) {
  46.192 +                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, 
  46.193 +                    "Callback to non-existing class " + fqn, e
  46.194 +                );
  46.195 +                return "";
  46.196 +            }
  46.197 +            ExecutableElement found = null;
  46.198 +            StringBuilder foundParams = new StringBuilder();
  46.199 +            for (Element m : type.getEnclosedElements()) {
  46.200 +                if (m.getKind() != ElementKind.METHOD) {
  46.201 +                    continue;
  46.202 +                }
  46.203 +                if (m.getSimpleName().contentEquals(method)) {
  46.204 +                    String paramTypes = findParamTypes((ExecutableElement)m);
  46.205 +                    if (paramTypes.equals(params)) {
  46.206 +                        found = (ExecutableElement) m;
  46.207 +                        break;
  46.208 +                    }
  46.209 +                    foundParams.append(paramTypes).append("\n");
  46.210 +                }
  46.211 +            }
  46.212 +            if (found == null) {
  46.213 +                if (foundParams.length() == 0) {
  46.214 +                    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, 
  46.215 +                        "Callback to class " + fqn + " with unknown method " + method, e
  46.216 +                    );
  46.217 +                } else {
  46.218 +                    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, 
  46.219 +                        "Callback to " + fqn + "." + method + " with wrong parameters: " + 
  46.220 +                        params + ". Only known parameters are " + foundParams, e
  46.221 +                    );
  46.222 +                }
  46.223 +            } else {
  46.224 +                Map<String,ExecutableElement> mangledOnes = javacalls.get(findPkg(e));
  46.225 +                if (mangledOnes == null) {
  46.226 +                    mangledOnes = new TreeMap<String, ExecutableElement>();
  46.227 +                    javacalls.put(findPkg(e), mangledOnes);
  46.228 +                }
  46.229 +                String mangled = JsCallback.mangle(fqn, method, findParamTypes(found));
  46.230 +                mangledOnes.put(mangled, found);
  46.231 +            }
  46.232 +            return "";
  46.233 +        }
  46.234 +
  46.235 +        private String findParamTypes(ExecutableElement method) {
  46.236 +            ExecutableType t = (ExecutableType) method.asType();
  46.237 +            StringBuilder sb = new StringBuilder();
  46.238 +            sb.append('(');
  46.239 +            for (TypeMirror tm : t.getParameterTypes()) {
  46.240 +                if (tm.getKind().isPrimitive()) {
  46.241 +                    switch (tm.getKind()) {
  46.242 +                        case INT: sb.append('I'); break;
  46.243 +                        case BOOLEAN: sb.append('Z'); break;
  46.244 +                        case BYTE: sb.append('B'); break;
  46.245 +                        case CHAR: sb.append('C'); break;
  46.246 +                        case SHORT: sb.append('S'); break;
  46.247 +                        case DOUBLE: sb.append('D'); break;
  46.248 +                        case FLOAT: sb.append('F'); break;
  46.249 +                        case LONG: sb.append('J'); break;
  46.250 +                        default:
  46.251 +                            throw new IllegalStateException("Uknown " + tm.getKind());
  46.252 +                    }
  46.253 +                } else {
  46.254 +                    while (tm.getKind() == TypeKind.ARRAY) {
  46.255 +                        sb.append('[');
  46.256 +                        tm = ((ArrayType)tm).getComponentType();
  46.257 +                    }
  46.258 +                    sb.append('L');
  46.259 +                    sb.append(tm.toString().replace('.', '/'));
  46.260 +                    sb.append(';');
  46.261 +                }
  46.262 +            }
  46.263 +            sb.append(')');
  46.264 +            return sb.toString();
  46.265 +        }
  46.266 +    }
  46.267 +    
  46.268 +    private void generateCallbackClass(Map<String,Map<String, ExecutableElement>> process) {
  46.269 +        for (Map.Entry<String, Map<String, ExecutableElement>> pkgEn : process.entrySet()) {
  46.270 +            String pkgName = pkgEn.getKey();
  46.271 +            Map<String, ExecutableElement> map = pkgEn.getValue();
  46.272 +            StringBuilder source = new StringBuilder();
  46.273 +            source.append("package ").append(pkgName).append(";\n");
  46.274 +            source.append("public final class $JsCallbacks$ {\n");
  46.275 +            source.append("  static final $JsCallbacks$ VM = new $JsCallbacks$(null);\n");
  46.276 +            source.append("  private final org.apidesign.html.boot.spi.Fn.Presenter p;\n");
  46.277 +            source.append("  private $JsCallbacks$ last;\n");
  46.278 +            source.append("  private $JsCallbacks$(org.apidesign.html.boot.spi.Fn.Presenter p) {\n");
  46.279 +            source.append("    this.p = p;\n");
  46.280 +            source.append("  }\n");
  46.281 +            source.append("  final $JsCallbacks$ current() {\n");
  46.282 +            source.append("    org.apidesign.html.boot.spi.Fn.Presenter now = org.apidesign.html.boot.spi.Fn.activePresenter();\n");
  46.283 +            source.append("    if (now == p) return this;\n");
  46.284 +            source.append("    if (last != null && now == last.p) return last;\n");
  46.285 +            source.append("    return last = new $JsCallbacks$(now);\n");
  46.286 +            source.append("  }\n");
  46.287 +            for (Map.Entry<String, ExecutableElement> entry : map.entrySet()) {
  46.288 +                final String mangled = entry.getKey();
  46.289 +                final ExecutableElement m = entry.getValue();
  46.290 +                final boolean isStatic = m.getModifiers().contains(Modifier.STATIC);
  46.291 +                
  46.292 +                source.append("\n  public java.lang.Object ")
  46.293 +                    .append(mangled)
  46.294 +                    .append("(");
  46.295 +                
  46.296 +                String sep = "";
  46.297 +                if (!isStatic) {
  46.298 +                    source.append(((TypeElement)m.getEnclosingElement()).getQualifiedName());
  46.299 +                    source.append(" self");
  46.300 +                    sep = ", ";
  46.301 +                }
  46.302 +                
  46.303 +                int cnt = 0;
  46.304 +                for (VariableElement ve : m.getParameters()) {
  46.305 +                    source.append(sep);
  46.306 +                    source.append(ve.asType());
  46.307 +                    source.append(" arg").append(++cnt);
  46.308 +                    sep = ", ";
  46.309 +                }
  46.310 +                source.append(") throws Throwable {\n");
  46.311 +                if (processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_7) >= 0) {
  46.312 +                    source.append("    try (java.io.Closeable a = org.apidesign.html.boot.spi.Fn.activate(p)) { \n");
  46.313 +                } else {
  46.314 +                    source.append("    java.io.Closeable a = org.apidesign.html.boot.spi.Fn.activate(p); try {\n");
  46.315 +                }
  46.316 +                source.append("    ");
  46.317 +                if (m.getReturnType().getKind() != TypeKind.VOID) {
  46.318 +                    source.append("return ");
  46.319 +                }
  46.320 +                if (isStatic) {
  46.321 +                    source.append(((TypeElement)m.getEnclosingElement()).getQualifiedName());
  46.322 +                    source.append('.');
  46.323 +                } else {
  46.324 +                    source.append("self.");
  46.325 +                }
  46.326 +                source.append(m.getSimpleName());
  46.327 +                source.append("(");
  46.328 +                cnt = 0;
  46.329 +                sep = "";
  46.330 +                for (VariableElement ve : m.getParameters()) {
  46.331 +                    source.append(sep);
  46.332 +                    source.append("arg").append(++cnt);
  46.333 +                    sep = ", ";
  46.334 +                }
  46.335 +                source.append(");\n");
  46.336 +                if (m.getReturnType().getKind() == TypeKind.VOID) {
  46.337 +                    source.append("    return null;\n");
  46.338 +                }
  46.339 +                if (processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_7) >= 0) {
  46.340 +                    source.append("    }\n");
  46.341 +                } else {
  46.342 +                    
  46.343 +                    source.append("    } finally {\n");
  46.344 +                    source.append("      a.close();\n");
  46.345 +                    source.append("    }\n");
  46.346 +                }
  46.347 +                source.append("  }\n");
  46.348 +            }
  46.349 +            source.append("}\n");
  46.350 +            final String srcName = pkgName + ".$JsCallbacks$";
  46.351 +            try {
  46.352 +                Writer w = processingEnv.getFiler().createSourceFile(srcName,
  46.353 +                    map.values().toArray(new Element[map.size()])
  46.354 +                ).openWriter();
  46.355 +                w.write(source.toString());
  46.356 +                w.close();
  46.357 +            } catch (IOException ex) {
  46.358 +                processingEnv.getMessager().printMessage(
  46.359 +                    Diagnostic.Kind.ERROR, "Can't write " + srcName + ": " + ex.getMessage()
  46.360 +                );
  46.361 +            }
  46.362 +        }
  46.363 +    }
  46.364 +    
  46.365 +    private static String findPkg(Element e) {
  46.366 +        while (e.getKind() != ElementKind.PACKAGE) {
  46.367 +            e = e.getEnclosingElement();
  46.368 +        }
  46.369 +        return ((PackageElement)e).getQualifiedName().toString();
  46.370 +    }
  46.371 +    
  46.372 +}
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/JsAgent.java	Tue Jan 07 08:21:57 2014 +0100
    47.3 @@ -0,0 +1,67 @@
    47.4 +/**
    47.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    47.6 + *
    47.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    47.8 + *
    47.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   47.10 + * Other names may be trademarks of their respective owners.
   47.11 + *
   47.12 + * The contents of this file are subject to the terms of either the GNU
   47.13 + * General Public License Version 2 only ("GPL") or the Common
   47.14 + * Development and Distribution License("CDDL") (collectively, the
   47.15 + * "License"). You may not use this file except in compliance with the
   47.16 + * License. You can obtain a copy of the License at
   47.17 + * http://www.netbeans.org/cddl-gplv2.html
   47.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   47.19 + * specific language governing permissions and limitations under the
   47.20 + * License.  When distributing the software, include this License Header
   47.21 + * Notice in each file and include the License file at
   47.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   47.23 + * particular file as subject to the "Classpath" exception as provided
   47.24 + * by Oracle in the GPL Version 2 section of the License file that
   47.25 + * accompanied this code. If applicable, add the following below the
   47.26 + * License Header, with the fields enclosed by brackets [] replaced by
   47.27 + * your own identifying information:
   47.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   47.29 + *
   47.30 + * Contributor(s):
   47.31 + *
   47.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   47.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   47.34 + *
   47.35 + * If you wish your version of this file to be governed by only the CDDL
   47.36 + * or only the GPL Version 2, indicate your decision by adding
   47.37 + * "[Contributor] elects to include this software in this distribution
   47.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   47.39 + * single choice of license, a recipient has the option to distribute
   47.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   47.41 + * to extend the choice of license to its licensees as provided above.
   47.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   47.43 + * Version 2 license, then the option applies only if the new code is
   47.44 + * made subject to such option by the copyright holder.
   47.45 + */
   47.46 +package org.netbeans.html.boot.impl;
   47.47 +
   47.48 +import java.lang.instrument.ClassFileTransformer;
   47.49 +import java.lang.instrument.IllegalClassFormatException;
   47.50 +import java.lang.instrument.Instrumentation;
   47.51 +import java.security.ProtectionDomain;
   47.52 +
   47.53 +/**
   47.54 + *
   47.55 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   47.56 + */
   47.57 +public final class JsAgent implements ClassFileTransformer {
   47.58 +    public static void agentmain(String args, Instrumentation instr) {
   47.59 +        instr.addTransformer(new JsAgent());
   47.60 +    }
   47.61 +
   47.62 +    @Override
   47.63 +    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
   47.64 +        try {
   47.65 +            return FnUtils.transform(classfileBuffer, loader);
   47.66 +        } catch (Exception ex) {
   47.67 +            return classfileBuffer;
   47.68 +        }
   47.69 +    }
   47.70 +}
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/JsCallback.java	Tue Jan 07 08:21:57 2014 +0100
    48.3 @@ -0,0 +1,160 @@
    48.4 +/**
    48.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    48.6 + *
    48.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    48.8 + *
    48.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   48.10 + * Other names may be trademarks of their respective owners.
   48.11 + *
   48.12 + * The contents of this file are subject to the terms of either the GNU
   48.13 + * General Public License Version 2 only ("GPL") or the Common
   48.14 + * Development and Distribution License("CDDL") (collectively, the
   48.15 + * "License"). You may not use this file except in compliance with the
   48.16 + * License. You can obtain a copy of the License at
   48.17 + * http://www.netbeans.org/cddl-gplv2.html
   48.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   48.19 + * specific language governing permissions and limitations under the
   48.20 + * License.  When distributing the software, include this License Header
   48.21 + * Notice in each file and include the License file at
   48.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   48.23 + * particular file as subject to the "Classpath" exception as provided
   48.24 + * by Oracle in the GPL Version 2 section of the License file that
   48.25 + * accompanied this code. If applicable, add the following below the
   48.26 + * License Header, with the fields enclosed by brackets [] replaced by
   48.27 + * your own identifying information:
   48.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   48.29 + *
   48.30 + * Contributor(s):
   48.31 + *
   48.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   48.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   48.34 + *
   48.35 + * If you wish your version of this file to be governed by only the CDDL
   48.36 + * or only the GPL Version 2, indicate your decision by adding
   48.37 + * "[Contributor] elects to include this software in this distribution
   48.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   48.39 + * single choice of license, a recipient has the option to distribute
   48.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   48.41 + * to extend the choice of license to its licensees as provided above.
   48.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   48.43 + * Version 2 license, then the option applies only if the new code is
   48.44 + * made subject to such option by the copyright holder.
   48.45 + */
   48.46 +package org.netbeans.html.boot.impl;
   48.47 +
   48.48 +
   48.49 +/**
   48.50 + *
   48.51 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   48.52 + */
   48.53 +abstract class JsCallback {
   48.54 +    final String parse(String body) {
   48.55 +        StringBuilder sb = new StringBuilder();
   48.56 +        int pos = 0;
   48.57 +        for (;;) {
   48.58 +            int next = body.indexOf(".@", pos);
   48.59 +            if (next == -1) {
   48.60 +                sb.append(body.substring(pos));
   48.61 +                body = sb.toString();
   48.62 +                break;
   48.63 +            }
   48.64 +            int ident = next;
   48.65 +            while (ident > 0) {
   48.66 +                if (!Character.isJavaIdentifierPart(body.charAt(--ident))) {
   48.67 +                    ident++;
   48.68 +                    break;
   48.69 +                }
   48.70 +            }
   48.71 +            String refId = body.substring(ident, next);
   48.72 +            
   48.73 +            sb.append(body.substring(pos, ident));
   48.74 +            
   48.75 +            int sigBeg = body.indexOf('(', next);
   48.76 +            int sigEnd = body.indexOf(')', sigBeg);
   48.77 +            int colon4 = body.indexOf("::", next);
   48.78 +            if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
   48.79 +                throw new IllegalStateException(
   48.80 +                    "Wrong format of instance callback. "
   48.81 +                    + "Should be: 'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n" 
   48.82 +                    + body
   48.83 +                );
   48.84 +            }
   48.85 +            String fqn = body.substring(next + 2, colon4);
   48.86 +            String method = body.substring(colon4 + 2, sigBeg);
   48.87 +            String params = body.substring(sigBeg, sigEnd + 1);
   48.88 +
   48.89 +            int paramBeg = body.indexOf('(', sigEnd + 1);
   48.90 +            if (paramBeg == -1) {
   48.91 +                throw new IllegalStateException(
   48.92 +                    "Wrong format of instance callback. "
   48.93 +                    + "Should be: 'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n" 
   48.94 +                    + body
   48.95 +                );
   48.96 +            }
   48.97 +            
   48.98 +            sb.append(callMethod(refId, fqn, method, params));
   48.99 +            if (body.charAt(paramBeg + 1) != (')')) {
  48.100 +                sb.append(",");
  48.101 +            }
  48.102 +            pos = paramBeg + 1;
  48.103 +        }
  48.104 +        pos = 0;
  48.105 +        sb = null;
  48.106 +        for (;;) {
  48.107 +            int next = body.indexOf("@", pos);
  48.108 +            if (next == -1) {
  48.109 +                if (sb == null) {
  48.110 +                    return body;
  48.111 +                }
  48.112 +                sb.append(body.substring(pos));
  48.113 +                return sb.toString();
  48.114 +            }
  48.115 +            if (sb == null) {
  48.116 +                sb = new StringBuilder();
  48.117 +            }
  48.118 +            
  48.119 +            sb.append(body.substring(pos, next));
  48.120 +            
  48.121 +            int sigBeg = body.indexOf('(', next);
  48.122 +            int sigEnd = body.indexOf(')', sigBeg);
  48.123 +            int colon4 = body.indexOf("::", next);
  48.124 +            if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
  48.125 +                throw new IllegalStateException(
  48.126 +                    "Wrong format of static callback. "
  48.127 +                    + "Should be: '@pkg.Class::staticMethod(Ljava/lang/Object;)(param)':\n" 
  48.128 +                    + body
  48.129 +                );
  48.130 +            }
  48.131 +            String fqn = body.substring(next + 1, colon4);
  48.132 +            String method = body.substring(colon4 + 2, sigBeg);
  48.133 +            String params = body.substring(sigBeg, sigEnd + 1);
  48.134 +
  48.135 +            int paramBeg = body.indexOf('(', sigEnd + 1);
  48.136 +            
  48.137 +            sb.append(callMethod(null, fqn, method, params));
  48.138 +            pos = paramBeg + 1;
  48.139 +        }
  48.140 +    }
  48.141 +
  48.142 +    protected abstract CharSequence callMethod(
  48.143 +        String ident, String fqn, String method, String params
  48.144 +    );
  48.145 +
  48.146 +    static String mangle(String fqn, String method, String params) {
  48.147 +        if (params.startsWith("(")) {
  48.148 +            params = params.substring(1);
  48.149 +        }
  48.150 +        if (params.endsWith(")")) {
  48.151 +            params = params.substring(0, params.length() - 1);
  48.152 +        }
  48.153 +        return 
  48.154 +            replace(fqn) + "$" + replace(method) + "$" + replace(params);
  48.155 +    }
  48.156 +    
  48.157 +    private static String replace(String orig) {
  48.158 +        return orig.replace("_", "_1").
  48.159 +            replace(";", "_2").
  48.160 +            replace("[", "_3").
  48.161 +            replace('.', '_').replace('/', '_');
  48.162 +    }
  48.163 +}
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/JsClassLoader.java	Tue Jan 07 08:21:57 2014 +0100
    49.3 @@ -0,0 +1,133 @@
    49.4 +/**
    49.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    49.6 + *
    49.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    49.8 + *
    49.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   49.10 + * Other names may be trademarks of their respective owners.
   49.11 + *
   49.12 + * The contents of this file are subject to the terms of either the GNU
   49.13 + * General Public License Version 2 only ("GPL") or the Common
   49.14 + * Development and Distribution License("CDDL") (collectively, the
   49.15 + * "License"). You may not use this file except in compliance with the
   49.16 + * License. You can obtain a copy of the License at
   49.17 + * http://www.netbeans.org/cddl-gplv2.html
   49.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   49.19 + * specific language governing permissions and limitations under the
   49.20 + * License.  When distributing the software, include this License Header
   49.21 + * Notice in each file and include the License file at
   49.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   49.23 + * particular file as subject to the "Classpath" exception as provided
   49.24 + * by Oracle in the GPL Version 2 section of the License file that
   49.25 + * accompanied this code. If applicable, add the following below the
   49.26 + * License Header, with the fields enclosed by brackets [] replaced by
   49.27 + * your own identifying information:
   49.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   49.29 + *
   49.30 + * Contributor(s):
   49.31 + *
   49.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   49.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   49.34 + *
   49.35 + * If you wish your version of this file to be governed by only the CDDL
   49.36 + * or only the GPL Version 2, indicate your decision by adding
   49.37 + * "[Contributor] elects to include this software in this distribution
   49.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   49.39 + * single choice of license, a recipient has the option to distribute
   49.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   49.41 + * to extend the choice of license to its licensees as provided above.
   49.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   49.43 + * Version 2 license, then the option applies only if the new code is
   49.44 + * made subject to such option by the copyright holder.
   49.45 + */
   49.46 +package org.netbeans.html.boot.impl;
   49.47 +
   49.48 +import org.apidesign.html.boot.spi.Fn;
   49.49 +import java.io.IOException;
   49.50 +import java.io.InputStream;
   49.51 +import java.io.Reader;
   49.52 +import java.net.URL;
   49.53 +import java.util.Enumeration;
   49.54 +
   49.55 +/** 
   49.56 + *
   49.57 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   49.58 + */
   49.59 +abstract class JsClassLoader extends ClassLoader {
   49.60 +    JsClassLoader(ClassLoader parent) {
   49.61 +        super(parent);
   49.62 +        setDefaultAssertionStatus(JsClassLoader.class.desiredAssertionStatus());
   49.63 +    }
   49.64 +    
   49.65 +    @Override
   49.66 +    protected abstract URL findResource(String name);
   49.67 +    
   49.68 +    @Override
   49.69 +    protected abstract Enumeration<URL> findResources(String name);
   49.70 +
   49.71 +    @Override
   49.72 +    protected Class<?> findClass(String name) throws ClassNotFoundException {
   49.73 +        if (name.startsWith("javafx")) {
   49.74 +            return Class.forName(name);
   49.75 +        }
   49.76 +        if (name.startsWith("netscape")) {
   49.77 +            return Class.forName(name);
   49.78 +        }
   49.79 +        if (name.startsWith("com.sun")) {
   49.80 +            return Class.forName(name);
   49.81 +        }
   49.82 +        if (name.equals(JsClassLoader.class.getName())) {
   49.83 +            return JsClassLoader.class;
   49.84 +        }
   49.85 +        if (name.equals(Fn.class.getName())) {
   49.86 +            return Fn.class;
   49.87 +        }
   49.88 +        if (name.equals(Fn.Presenter.class.getName())) {
   49.89 +            return Fn.Presenter.class;
   49.90 +        }
   49.91 +        if (name.equals(FnUtils.class.getName())) {
   49.92 +            return FnUtils.class;
   49.93 +        }
   49.94 +        if (
   49.95 +            name.equals("org.apidesign.html.boot.spi.Fn") ||
   49.96 +            name.equals("org.netbeans.html.boot.impl.FnUtils") ||
   49.97 +            name.equals("org.netbeans.html.boot.impl.FnContext")
   49.98 +        ) {
   49.99 +            return Class.forName(name);
  49.100 +        }
  49.101 +        URL u = findResource(name.replace('.', '/') + ".class");
  49.102 +        if (u != null) {
  49.103 +            InputStream is = null;
  49.104 +            try {
  49.105 +                is = u.openStream();
  49.106 +                byte[] arr = new byte[is.available()];
  49.107 +                int len = 0;
  49.108 +                while (len < arr.length) {
  49.109 +                    int read = is.read(arr, len, arr.length - len);
  49.110 +                    if (read == -1) {
  49.111 +                        throw new IOException("Can't read " + u);
  49.112 +                    }
  49.113 +                    len += read;
  49.114 +                }
  49.115 +                is.close();
  49.116 +                is = null;
  49.117 +                arr = FnUtils.transform(arr, JsClassLoader.this);
  49.118 +                if (arr != null) {
  49.119 +                    return defineClass(name, arr, 0, arr.length);
  49.120 +                }
  49.121 +            } catch (IOException ex) {
  49.122 +                throw new ClassNotFoundException("Can't load " + name, ex);
  49.123 +            } finally {
  49.124 +                try {
  49.125 +                    if (is != null) is.close();
  49.126 +                } catch (IOException ex) {
  49.127 +                    throw new ClassNotFoundException(null, ex);
  49.128 +                }
  49.129 +            }
  49.130 +        }
  49.131 +        return super.findClass(name);
  49.132 +    }
  49.133 +    
  49.134 +    protected abstract Fn defineFn(String code, String... names);
  49.135 +    protected abstract void loadScript(Reader code) throws Exception;
  49.136 +}
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/Test.java	Tue Jan 07 08:21:57 2014 +0100
    50.3 @@ -0,0 +1,57 @@
    50.4 +/**
    50.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    50.6 + *
    50.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    50.8 + *
    50.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   50.10 + * Other names may be trademarks of their respective owners.
   50.11 + *
   50.12 + * The contents of this file are subject to the terms of either the GNU
   50.13 + * General Public License Version 2 only ("GPL") or the Common
   50.14 + * Development and Distribution License("CDDL") (collectively, the
   50.15 + * "License"). You may not use this file except in compliance with the
   50.16 + * License. You can obtain a copy of the License at
   50.17 + * http://www.netbeans.org/cddl-gplv2.html
   50.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   50.19 + * specific language governing permissions and limitations under the
   50.20 + * License.  When distributing the software, include this License Header
   50.21 + * Notice in each file and include the License file at
   50.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   50.23 + * particular file as subject to the "Classpath" exception as provided
   50.24 + * by Oracle in the GPL Version 2 section of the License file that
   50.25 + * accompanied this code. If applicable, add the following below the
   50.26 + * License Header, with the fields enclosed by brackets [] replaced by
   50.27 + * your own identifying information:
   50.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   50.29 + *
   50.30 + * Contributor(s):
   50.31 + *
   50.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   50.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   50.34 + *
   50.35 + * If you wish your version of this file to be governed by only the CDDL
   50.36 + * or only the GPL Version 2, indicate your decision by adding
   50.37 + * "[Contributor] elects to include this software in this distribution
   50.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   50.39 + * single choice of license, a recipient has the option to distribute
   50.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   50.41 + * to extend the choice of license to its licensees as provided above.
   50.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   50.43 + * Version 2 license, then the option applies only if the new code is
   50.44 + * made subject to such option by the copyright holder.
   50.45 + */
   50.46 +package org.netbeans.html.boot.impl;
   50.47 +
   50.48 +import java.util.concurrent.Callable;
   50.49 +import net.java.html.js.JavaScriptBody;
   50.50 +
   50.51 +/**
   50.52 + *
   50.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   50.54 + */
   50.55 +public final class Test implements Callable<Boolean> {
   50.56 +    @Override @JavaScriptBody(args = {}, body = "return true;")
   50.57 +    public Boolean call() {
   50.58 +        return false;
   50.59 +    }
   50.60 +}
    51.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/Arithm.java	Thu Dec 19 17:11:01 2013 +0100
    51.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.3 @@ -1,31 +0,0 @@
    51.4 -/**
    51.5 - * HTML via Java(tm) Language Bindings
    51.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    51.7 - *
    51.8 - * This program is free software: you can redistribute it and/or modify
    51.9 - * it under the terms of the GNU General Public License as published by
   51.10 - * the Free Software Foundation, version 2 of the License.
   51.11 - *
   51.12 - * This program is distributed in the hope that it will be useful,
   51.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   51.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   51.15 - * GNU General Public License for more details. apidesign.org
   51.16 - * designates this particular file as subject to the
   51.17 - * "Classpath" exception as provided by apidesign.org
   51.18 - * in the License file that accompanied this code.
   51.19 - *
   51.20 - * You should have received a copy of the GNU General Public License
   51.21 - * along with this program. Look for COPYING file in the top folder.
   51.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   51.23 - */
   51.24 -package org.apidesign.html.boot.impl;
   51.25 -
   51.26 -/**
   51.27 - *
   51.28 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   51.29 - */
   51.30 -public class Arithm {
   51.31 -    public int sumTwo(int a, int b) {
   51.32 -        return a + b;
   51.33 -    }
   51.34 -}
    52.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/Compile.java	Thu Dec 19 17:11:01 2013 +0100
    52.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.3 @@ -1,269 +0,0 @@
    52.4 -/**
    52.5 - * HTML via Java(tm) Language Bindings
    52.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    52.7 - *
    52.8 - * This program is free software: you can redistribute it and/or modify
    52.9 - * it under the terms of the GNU General Public License as published by
   52.10 - * the Free Software Foundation, version 2 of the License.
   52.11 - *
   52.12 - * This program is distributed in the hope that it will be useful,
   52.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   52.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   52.15 - * GNU General Public License for more details. apidesign.org
   52.16 - * designates this particular file as subject to the
   52.17 - * "Classpath" exception as provided by apidesign.org
   52.18 - * in the License file that accompanied this code.
   52.19 - *
   52.20 - * You should have received a copy of the GNU General Public License
   52.21 - * along with this program. Look for COPYING file in the top folder.
   52.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   52.23 - */
   52.24 -package org.apidesign.html.boot.impl;
   52.25 -
   52.26 -import java.io.ByteArrayInputStream;
   52.27 -import java.io.ByteArrayOutputStream;
   52.28 -import java.io.IOException;
   52.29 -import java.io.InputStream;
   52.30 -import java.io.OutputStream;
   52.31 -import java.net.URI;
   52.32 -import java.net.URISyntaxException;
   52.33 -import java.util.ArrayList;
   52.34 -import java.util.Arrays;
   52.35 -import java.util.HashMap;
   52.36 -import java.util.List;
   52.37 -import java.util.Locale;
   52.38 -import java.util.Map;
   52.39 -import java.util.regex.Matcher;
   52.40 -import java.util.regex.Pattern;
   52.41 -import javax.tools.Diagnostic;
   52.42 -import javax.tools.DiagnosticListener;
   52.43 -import javax.tools.FileObject;
   52.44 -import javax.tools.ForwardingJavaFileManager;
   52.45 -import javax.tools.JavaFileManager;
   52.46 -import javax.tools.JavaFileObject;
   52.47 -import javax.tools.JavaFileObject.Kind;
   52.48 -import javax.tools.SimpleJavaFileObject;
   52.49 -import javax.tools.StandardJavaFileManager;
   52.50 -import javax.tools.StandardLocation;
   52.51 -import javax.tools.ToolProvider;
   52.52 -import static org.testng.Assert.assertTrue;
   52.53 -import static org.testng.Assert.assertFalse;
   52.54 -import static org.testng.Assert.fail;
   52.55 -
   52.56 -/**
   52.57 - *
   52.58 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   52.59 - */
   52.60 -final class Compile implements DiagnosticListener<JavaFileObject> {
   52.61 -    private final List<Diagnostic<? extends JavaFileObject>> errors = 
   52.62 -            new ArrayList<Diagnostic<? extends JavaFileObject>>();
   52.63 -    private final Map<String, byte[]> classes;
   52.64 -    private final String pkg;
   52.65 -    private final String cls;
   52.66 -    private final String html;
   52.67 -    private final String sourceLevel;
   52.68 -
   52.69 -    private Compile(String html, String code, String sl) throws IOException {
   52.70 -        this.pkg = findPkg(code);
   52.71 -        this.cls = findCls(code);
   52.72 -        this.html = html;
   52.73 -        this.sourceLevel = sl;
   52.74 -        classes = compile(html, code);
   52.75 -    }
   52.76 -
   52.77 -    /** Performs compilation of given HTML page and associated Java code
   52.78 -     */
   52.79 -    public static Compile create(String html, String code) throws IOException {
   52.80 -        return create(html, code, "1.7");
   52.81 -    }
   52.82 -    static Compile create(String html, String code, String sourceLevel) throws IOException {
   52.83 -        return new Compile(html, code, sourceLevel);
   52.84 -    }
   52.85 -    
   52.86 -    /** Checks for given class among compiled resources */
   52.87 -    public byte[] get(String res) {
   52.88 -        return classes.get(res);
   52.89 -    }
   52.90 -    
   52.91 -    /** Obtains errors created during compilation.
   52.92 -     */
   52.93 -    public List<Diagnostic<? extends JavaFileObject>> getErrors() {
   52.94 -        List<Diagnostic<? extends JavaFileObject>> err;
   52.95 -        err = new ArrayList<Diagnostic<? extends JavaFileObject>>();
   52.96 -        for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
   52.97 -            if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
   52.98 -                err.add(diagnostic);
   52.99 -            }
  52.100 -        }
  52.101 -        return err;
  52.102 -    }
  52.103 -    
  52.104 -    private Map<String, byte[]> compile(final String html, final String code) throws IOException {
  52.105 -        StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
  52.106 -
  52.107 -        final Map<String, ByteArrayOutputStream> class2BAOS;
  52.108 -        class2BAOS = new HashMap<String, ByteArrayOutputStream>();
  52.109 -
  52.110 -        JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
  52.111 -            @Override
  52.112 -            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  52.113 -                return code;
  52.114 -            }
  52.115 -        };
  52.116 -        final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
  52.117 -            @Override
  52.118 -            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  52.119 -                return html;
  52.120 -            }
  52.121 -
  52.122 -            @Override
  52.123 -            public InputStream openInputStream() throws IOException {
  52.124 -                return new ByteArrayInputStream(html.getBytes());
  52.125 -            }
  52.126 -        };
  52.127 -        
  52.128 -        final URI scratch;
  52.129 -        try {
  52.130 -            scratch = new URI("mem://mem3");
  52.131 -        } catch (URISyntaxException ex) {
  52.132 -            throw new IOException(ex);
  52.133 -        }
  52.134 -        
  52.135 -        JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
  52.136 -            @Override
  52.137 -            public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
  52.138 -                if (kind  == Kind.CLASS) {
  52.139 -                    final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
  52.140 -
  52.141 -                    class2BAOS.put(className.replace('.', '/') + ".class", buffer);
  52.142 -                    return new SimpleJavaFileObject(sibling.toUri(), kind) {
  52.143 -                        @Override
  52.144 -                        public OutputStream openOutputStream() throws IOException {
  52.145 -                            return buffer;
  52.146 -                        }
  52.147 -                    };
  52.148 -                }
  52.149 -                
  52.150 -                if (kind == Kind.SOURCE) {
  52.151 -                    final String n = className.replace('.', '/') + ".java";
  52.152 -                    final URI un;
  52.153 -                    try {
  52.154 -                        un = new URI("mem://" + n);
  52.155 -                    } catch (URISyntaxException ex) {
  52.156 -                        throw new IOException(ex);
  52.157 -                    }
  52.158 -                    return new VirtFO(un/*sibling.toUri()*/, kind, n);
  52.159 -                }
  52.160 -                
  52.161 -                throw new IllegalStateException();
  52.162 -            }
  52.163 -
  52.164 -            @Override
  52.165 -            public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
  52.166 -                if (location == StandardLocation.SOURCE_PATH) {
  52.167 -                    if (packageName.equals(pkg)) {
  52.168 -                        return htmlFile;
  52.169 -                    }
  52.170 -                }
  52.171 -                
  52.172 -                return null;
  52.173 -            }
  52.174 -
  52.175 -            @Override
  52.176 -            public boolean isSameFile(FileObject a, FileObject b) {
  52.177 -                if (a instanceof VirtFO && b instanceof VirtFO) {
  52.178 -                    return ((VirtFO)a).getName().equals(((VirtFO)b).getName());
  52.179 -                }
  52.180 -                
  52.181 -                return super.isSameFile(a, b);
  52.182 -            }
  52.183 -
  52.184 -            class VirtFO extends SimpleJavaFileObject {
  52.185 -
  52.186 -                private final String n;
  52.187 -
  52.188 -                public VirtFO(URI uri, Kind kind, String n) {
  52.189 -                    super(uri, kind);
  52.190 -                    this.n = n;
  52.191 -                }
  52.192 -                private final ByteArrayOutputStream data = new ByteArrayOutputStream();
  52.193 -
  52.194 -                @Override
  52.195 -                public OutputStream openOutputStream() throws IOException {
  52.196 -                    return data;
  52.197 -                }
  52.198 -
  52.199 -                @Override
  52.200 -                public String getName() {
  52.201 -                    return n;
  52.202 -                }
  52.203 -
  52.204 -                @Override
  52.205 -                public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  52.206 -                    data.close();
  52.207 -                    return new String(data.toByteArray());
  52.208 -                }
  52.209 -            }
  52.210 -        };
  52.211 -
  52.212 -        ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", sourceLevel, "-target", "1.7"), null, Arrays.asList(file)).call();
  52.213 -
  52.214 -        Map<String, byte[]> result = new HashMap<String, byte[]>();
  52.215 -
  52.216 -        for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
  52.217 -            result.put(e.getKey(), e.getValue().toByteArray());
  52.218 -        }
  52.219 -
  52.220 -        return result;
  52.221 -    }
  52.222 -
  52.223 -
  52.224 -    @Override
  52.225 -    public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
  52.226 -        errors.add(diagnostic);
  52.227 -    }
  52.228 -    private static String findPkg(String java) throws IOException {
  52.229 -        Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
  52.230 -        Matcher m = p.matcher(java);
  52.231 -        if (!m.find()) {
  52.232 -            throw new IOException("Can't find package declaration in the java file");
  52.233 -        }
  52.234 -        String pkg = m.group(1);
  52.235 -        return pkg;
  52.236 -    }
  52.237 -    private static String findCls(String java) throws IOException {
  52.238 -        Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
  52.239 -        Matcher m = p.matcher(java);
  52.240 -        if (!m.find()) {
  52.241 -            throw new IOException("Can't find package declaration in the java file");
  52.242 -        }
  52.243 -        String cls = m.group(1);
  52.244 -        return cls;
  52.245 -    }
  52.246 -
  52.247 -    String getHtml() {
  52.248 -        String fqn = "'" + pkg + '.' + cls + "'";
  52.249 -        return html.replace("'${fqn}'", fqn);
  52.250 -    }
  52.251 -    void assertErrors() {
  52.252 -        assertFalse(getErrors().isEmpty(), "There are supposed to be some errors");
  52.253 -    }
  52.254 -
  52.255 -    void assertError(String expMsg) {
  52.256 -        StringBuilder sb = new StringBuilder();
  52.257 -        sb.append("Can't find ").append(expMsg).append(" among:");
  52.258 -        for (Diagnostic<? extends JavaFileObject> e : errors) {
  52.259 -            String msg = e.getMessage(Locale.US);
  52.260 -            if (msg.contains(expMsg)) {
  52.261 -                return;
  52.262 -            }
  52.263 -            sb.append("\n");
  52.264 -            sb.append(msg);
  52.265 -        }
  52.266 -        fail(sb.toString());
  52.267 -    }
  52.268 -
  52.269 -    void assertNoErrors() {
  52.270 -        assertTrue(getErrors().isEmpty(), "No errors expected: " + getErrors());
  52.271 -    }
  52.272 -}
    53.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/FnTest.java	Thu Dec 19 17:11:01 2013 +0100
    53.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.3 @@ -1,127 +0,0 @@
    53.4 -/**
    53.5 - * HTML via Java(tm) Language Bindings
    53.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    53.7 - *
    53.8 - * This program is free software: you can redistribute it and/or modify
    53.9 - * it under the terms of the GNU General Public License as published by
   53.10 - * the Free Software Foundation, version 2 of the License.
   53.11 - *
   53.12 - * This program is distributed in the hope that it will be useful,
   53.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   53.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   53.15 - * GNU General Public License for more details. apidesign.org
   53.16 - * designates this particular file as subject to the
   53.17 - * "Classpath" exception as provided by apidesign.org
   53.18 - * in the License file that accompanied this code.
   53.19 - *
   53.20 - * You should have received a copy of the GNU General Public License
   53.21 - * along with this program. Look for COPYING file in the top folder.
   53.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   53.23 - */
   53.24 -
   53.25 -package org.apidesign.html.boot.impl;
   53.26 -
   53.27 -import java.io.Closeable;
   53.28 -import java.io.Reader;
   53.29 -import java.net.URL;
   53.30 -import java.net.URLClassLoader;
   53.31 -import java.util.ArrayList;
   53.32 -import java.util.Arrays;
   53.33 -import java.util.Collection;
   53.34 -import java.util.List;
   53.35 -import javax.script.Invocable;
   53.36 -import javax.script.ScriptEngine;
   53.37 -import javax.script.ScriptEngineManager;
   53.38 -import javax.script.ScriptException;
   53.39 -import org.apidesign.html.boot.spi.Fn;
   53.40 -import org.testng.annotations.BeforeClass;
   53.41 -import org.testng.annotations.BeforeMethod;
   53.42 -
   53.43 -/**
   53.44 - *
   53.45 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   53.46 - */
   53.47 -public class FnTest extends JsClassLoaderBase {
   53.48 -    private static Fn.Presenter presenter;
   53.49 -    
   53.50 -    public FnTest() {
   53.51 -    }
   53.52 -
   53.53 -    @BeforeClass
   53.54 -    public static void createClassLoader() throws Exception {
   53.55 -        ScriptEngineManager sem = new ScriptEngineManager();
   53.56 -        final ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
   53.57 -        
   53.58 -        final URL my = FnTest.class.getProtectionDomain().getCodeSource().getLocation();
   53.59 -        ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
   53.60 -        final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
   53.61 -        
   53.62 -        class Impl implements FindResources, Fn.Presenter {
   53.63 -            @Override
   53.64 -            public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough) {
   53.65 -                URL u = ul.findResource(path);
   53.66 -                if (u != null) {
   53.67 -                    results.add(u);
   53.68 -                }
   53.69 -            }
   53.70 -
   53.71 -            @Override
   53.72 -            public Fn defineFn(String code, String... names) {
   53.73 -                StringBuilder sb = new StringBuilder();
   53.74 -                sb.append("(function() {");
   53.75 -                sb.append("return function(");
   53.76 -                String sep = "";
   53.77 -                for (String n : names) {
   53.78 -                    sb.append(sep);
   53.79 -                    sb.append(n);
   53.80 -                    sep = ", ";
   53.81 -                }
   53.82 -                sb.append(") {");
   53.83 -                sb.append(code);
   53.84 -                sb.append("};");
   53.85 -                sb.append("})()");
   53.86 -                try {
   53.87 -                    final Object val = eng.eval(sb.toString());
   53.88 -                    return new Fn(this) {
   53.89 -                        @Override
   53.90 -                        public Object invoke(Object thiz, Object... args) throws Exception {
   53.91 -                            List<Object> all = new ArrayList<Object>(args.length + 1);
   53.92 -                            all.add(thiz == null ? val : thiz);
   53.93 -                            all.addAll(Arrays.asList(args));
   53.94 -                            Invocable inv = (Invocable)eng;
   53.95 -                            try {
   53.96 -                                Object ret = inv.invokeMethod(val, "call", all.toArray());
   53.97 -                                return val.equals(ret) ? null : ret;
   53.98 -                            } catch (ScriptException ex) {
   53.99 -                                throw ex;
  53.100 -                            }
  53.101 -                        }
  53.102 -                    };
  53.103 -                } catch (ScriptException ex) {
  53.104 -                    throw new LinkageError("Can't parse: " + sb, ex);
  53.105 -                }
  53.106 -            }
  53.107 -
  53.108 -            @Override
  53.109 -            public void displayPage(URL resource, Runnable r) {
  53.110 -                throw new UnsupportedOperationException();
  53.111 -            }
  53.112 -
  53.113 -            @Override
  53.114 -            public void loadScript(Reader code) throws Exception {
  53.115 -                eng.eval(code);
  53.116 -            }
  53.117 -        }
  53.118 -        Impl impl = new Impl();
  53.119 -        ClassLoader loader = FnUtils.newLoader(impl, impl, parent);
  53.120 -        presenter = impl;
  53.121 -        
  53.122 -        Closeable close = FnContext.activate(impl);
  53.123 -        methodClass = loader.loadClass(JsMethods.class.getName());
  53.124 -        close.close();
  53.125 -    }
  53.126 -
  53.127 -    @BeforeMethod public void initPresenter() {
  53.128 -        FnContext.currentPresenter(presenter);
  53.129 -    }
  53.130 -}
    54.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JavaScriptProcesorTest.java	Thu Dec 19 17:11:01 2013 +0100
    54.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.3 @@ -1,107 +0,0 @@
    54.4 -/**
    54.5 - * HTML via Java(tm) Language Bindings
    54.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    54.7 - *
    54.8 - * This program is free software: you can redistribute it and/or modify
    54.9 - * it under the terms of the GNU General Public License as published by
   54.10 - * the Free Software Foundation, version 2 of the License.
   54.11 - *
   54.12 - * This program is distributed in the hope that it will be useful,
   54.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   54.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   54.15 - * GNU General Public License for more details. apidesign.org
   54.16 - * designates this particular file as subject to the
   54.17 - * "Classpath" exception as provided by apidesign.org
   54.18 - * in the License file that accompanied this code.
   54.19 - *
   54.20 - * You should have received a copy of the GNU General Public License
   54.21 - * along with this program. Look for COPYING file in the top folder.
   54.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   54.23 - */
   54.24 -package org.apidesign.html.boot.impl;
   54.25 -
   54.26 -import java.io.IOException;
   54.27 -import java.lang.reflect.Field;
   54.28 -import java.lang.reflect.Method;
   54.29 -import static org.testng.Assert.assertEquals;
   54.30 -import static org.testng.Assert.assertTrue;
   54.31 -import org.testng.annotations.Test;
   54.32 -
   54.33 -/**
   54.34 - *
   54.35 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   54.36 - */
   54.37 -public class JavaScriptProcesorTest {
   54.38 -    
   54.39 -    @Test public void detectCallbackToNonExistingClass() throws IOException {
   54.40 -        String code = "package x.y.z;\n"
   54.41 -            + "import net.java.html.js.JavaScriptBody;\n"
   54.42 -            + "class X {\n"
   54.43 -            + "  @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
   54.44 -            + "    \"r.@java.lang.Runable::run()();\"\n" // typo
   54.45 -            + "  )\n"
   54.46 -            + "  private static native void callback(Runnable r);\n"
   54.47 -            + "}\n";
   54.48 -        
   54.49 -        Compile c = Compile.create("", code);
   54.50 -        c.assertErrors();
   54.51 -        c.assertError("java.lang.Runable"); // typo
   54.52 -    }
   54.53 -
   54.54 -    @Test public void detectCallbackToNonExistingMethod() throws IOException {
   54.55 -        String code = "package x.y.z;\n"
   54.56 -            + "import net.java.html.js.JavaScriptBody;\n"
   54.57 -            + "class X {\n"
   54.58 -            + "  @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
   54.59 -            + "    \"r.@java.lang.Runnable::cancel()();\"\n"
   54.60 -            + "  )\n"
   54.61 -            + "  private static native void callback(Runnable r);\n"
   54.62 -            + "}\n";
   54.63 -        
   54.64 -        Compile c = Compile.create("", code);
   54.65 -        c.assertErrors();
   54.66 -        c.assertError("method cancel");
   54.67 -    }
   54.68 -
   54.69 -    @Test public void detectCallbackToNonExistingParams() throws IOException {
   54.70 -        String code = "package x.y.z;\n"
   54.71 -            + "import net.java.html.js.JavaScriptBody;\n"
   54.72 -            + "class X {\n"
   54.73 -            + "  @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
   54.74 -            + "    \"r.@java.lang.Runnable::run(I)(10);\"\n"
   54.75 -            + "  )\n"
   54.76 -            + "  private static native void callback(Runnable r);\n"
   54.77 -            + "}\n";
   54.78 -        
   54.79 -        Compile c = Compile.create("", code);
   54.80 -        c.assertErrors();
   54.81 -        c.assertError("wrong parameters: (I)");
   54.82 -    }
   54.83 -
   54.84 -    @Test public void objectTypeParamsAreOK() throws IOException {
   54.85 -        String code = "package x.y.z;\n"
   54.86 -            + "import net.java.html.js.JavaScriptBody;\n"
   54.87 -            + "class X {\n"
   54.88 -            + "  @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
   54.89 -            + "    \"r.@java.lang.Object::equals(Ljava/lang/Object;)(null);\"\n"
   54.90 -            + "  )\n"
   54.91 -            + "  private static native void testEqual(Object r);\n"
   54.92 -            + "}\n";
   54.93 -        
   54.94 -        Compile c = Compile.create("", code);
   54.95 -        c.assertNoErrors();
   54.96 -    }
   54.97 -    
   54.98 -    @Test public void generatesCallbacksThatReturnObject() throws Exception {
   54.99 -        Class<?> callbacksForTestPkg = Class.forName("org.apidesign.html.boot.impl.$JsCallbacks$");
  54.100 -        Method m = callbacksForTestPkg.getDeclaredMethod("java_lang_Runnable$run$", Runnable.class);
  54.101 -        assertEquals(m.getReturnType(), Object.class, "All methods always return object");
  54.102 -    }
  54.103 -    
  54.104 -    @Test public void hasInstanceField() throws Exception {
  54.105 -        Class<?> callbacksForTestPkg = Class.forName("org.apidesign.html.boot.impl.$JsCallbacks$");
  54.106 -        Field f = callbacksForTestPkg.getDeclaredField("VM");
  54.107 -        f.setAccessible(true);
  54.108 -        assertTrue(callbacksForTestPkg.isInstance(f.get(null)), "Singleton field VM");
  54.109 -    }
  54.110 -}
    55.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JsClassLoaderBase.java	Thu Dec 19 17:11:01 2013 +0100
    55.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.3 @@ -1,179 +0,0 @@
    55.4 -/**
    55.5 - * HTML via Java(tm) Language Bindings
    55.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    55.7 - *
    55.8 - * This program is free software: you can redistribute it and/or modify
    55.9 - * it under the terms of the GNU General Public License as published by
   55.10 - * the Free Software Foundation, version 2 of the License.
   55.11 - *
   55.12 - * This program is distributed in the hope that it will be useful,
   55.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   55.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   55.15 - * GNU General Public License for more details. apidesign.org
   55.16 - * designates this particular file as subject to the
   55.17 - * "Classpath" exception as provided by apidesign.org
   55.18 - * in the License file that accompanied this code.
   55.19 - *
   55.20 - * You should have received a copy of the GNU General Public License
   55.21 - * along with this program. Look for COPYING file in the top folder.
   55.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   55.23 - */
   55.24 -package org.apidesign.html.boot.impl;
   55.25 -
   55.26 -import java.lang.reflect.InvocationTargetException;
   55.27 -import java.lang.reflect.Method;
   55.28 -import java.lang.reflect.Modifier;
   55.29 -import static org.testng.Assert.*;
   55.30 -import org.testng.annotations.BeforeMethod;
   55.31 -import org.testng.annotations.Test;
   55.32 -
   55.33 -/**
   55.34 - *
   55.35 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   55.36 - */
   55.37 -public class JsClassLoaderBase {
   55.38 -    protected static Class<?> methodClass;
   55.39 -    
   55.40 -    public JsClassLoaderBase() {
   55.41 -    }
   55.42 -    
   55.43 -    @BeforeMethod
   55.44 -    public void assertClassDefined() {
   55.45 -        assertNotNull(methodClass, "BeforeClass set up code should provide methodClass");
   55.46 -    }
   55.47 -
   55.48 -    @Test public void noParamMethod() throws Throwable {
   55.49 -        Method plus = methodClass.getMethod("fortyTwo");
   55.50 -        try {
   55.51 -            final Object val = plus.invoke(null);
   55.52 -            assertTrue(val instanceof Number, "A number returned " + val);
   55.53 -            assertEquals(((Number)val).intValue(), 42);
   55.54 -        } catch (InvocationTargetException ex) {
   55.55 -            throw ex.getTargetException();
   55.56 -        }
   55.57 -    }
   55.58 -    
   55.59 -    @Test public void testExecuteScript() throws Throwable {
   55.60 -        Method plus = methodClass.getMethod("plus", int.class, int.class);
   55.61 -        try {
   55.62 -            assertEquals(plus.invoke(null, 10, 20), 30);
   55.63 -        } catch (InvocationTargetException ex) {
   55.64 -            throw ex.getTargetException();
   55.65 -        }
   55.66 -    }
   55.67 -
   55.68 -    @Test public void overloadedMethod() throws Throwable {
   55.69 -        Method plus = methodClass.getMethod("plus", int.class);
   55.70 -        try {
   55.71 -            assertEquals(plus.invoke(null, 10), 10);
   55.72 -        } catch (InvocationTargetException ex) {
   55.73 -            throw ex.getTargetException();
   55.74 -        }
   55.75 -    }
   55.76 -    
   55.77 -    @Test public void instanceMethod() throws Throwable {
   55.78 -        Method plus = methodClass.getMethod("plusInst", int.class);
   55.79 -        Object inst = methodClass.newInstance();
   55.80 -        try {
   55.81 -            assertEquals(plus.invoke(inst, 10), 10);
   55.82 -        } catch (InvocationTargetException ex) {
   55.83 -            throw ex.getTargetException();
   55.84 -        }
   55.85 -    }
   55.86 -    
   55.87 -    @Test public void staticThis() throws Throwable {
   55.88 -        Method st = methodClass.getMethod("staticThis");
   55.89 -        try {
   55.90 -            assertNull(st.invoke(null));
   55.91 -        } catch (InvocationTargetException ex) {
   55.92 -            throw ex.getTargetException();
   55.93 -        }
   55.94 -    }
   55.95 -
   55.96 -    @Test public void getThis() throws Throwable {
   55.97 -        Object th = methodClass.newInstance();
   55.98 -        Method st = methodClass.getMethod("getThis");
   55.99 -        try {
  55.100 -            assertEquals(st.invoke(th), th);
  55.101 -        } catch (InvocationTargetException ex) {
  55.102 -            throw ex.getTargetException();
  55.103 -        }
  55.104 -    }
  55.105 -    
  55.106 -    @Test public void truth() throws Throwable {
  55.107 -        Method st = methodClass.getMethod("truth");
  55.108 -        assertTrue((st.getModifiers() & Modifier.STATIC) != 0, "Is static");
  55.109 -        assertEquals(st.invoke(null), Boolean.TRUE, "Can return boolean");
  55.110 -    }
  55.111 -    
  55.112 -    @Test public void callback() throws Throwable {
  55.113 -        class R implements Runnable {
  55.114 -            int cnt;
  55.115 -            
  55.116 -            @Override
  55.117 -            public void run() {
  55.118 -                cnt++;
  55.119 -            }
  55.120 -        }
  55.121 -        R r = new R();
  55.122 -        
  55.123 -        Method inc = methodClass.getMethod("callback", Runnable.class);
  55.124 -        inc.invoke(null, r);
  55.125 -        
  55.126 -        assertEquals(r.cnt, 1, "Callback happened");
  55.127 -    }
  55.128 -    
  55.129 -    @Test public void sumArray() throws Throwable {
  55.130 -        Method st = methodClass.getMethod("sumArr", int[].class);
  55.131 -        assertEquals(st.invoke(null, new int[] { 1, 2, 3 }), 6, "1+2+3 is six");
  55.132 -    }
  55.133 -    
  55.134 -    @Test public void javaScriptResource() throws Throwable {
  55.135 -        try {
  55.136 -            Method st = methodClass.getMethod("useExternalMul", int.class, int.class);
  55.137 -            assertEquals(st.invoke(null, 6, 7), 42, "Meaning of JavaScript?");
  55.138 -        } catch (InvocationTargetException ex) {
  55.139 -            throw ex.getTargetException();
  55.140 -        }
  55.141 -    }
  55.142 -    
  55.143 -    @Test public void callJavaScriptMethodOnOwnClass() throws Throwable {
  55.144 -        try {
  55.145 -            Object thiz = methodClass.newInstance();
  55.146 -            Method st = methodClass.getMethod("returnYourSelf", methodClass);
  55.147 -            assertEquals(st.invoke(null, thiz), thiz, "Returns this");
  55.148 -        } catch (InvocationTargetException ex) {
  55.149 -            throw ex.getTargetException();
  55.150 -        }
  55.151 -    }
  55.152 -    
  55.153 -    @Test public void callStaticJavaMethod() throws Throwable {
  55.154 -        Method st = methodClass.getMethod("staticCallback", int.class, int.class);
  55.155 -        assertEquals(st.invoke(null, 6, 7), 42, "Meaning of JavaScript?");
  55.156 -    }
  55.157 -
  55.158 -    @Test public void callStaticStringParamMethod() throws Throwable {
  55.159 -        Method st = methodClass.getMethod("parseInt", String.class);
  55.160 -        assertEquals(st.invoke(null, "42"), 42, "Meaning of JavaScript?");
  55.161 -    }
  55.162 -    
  55.163 -    @Test public void firstLong() throws Throwable {
  55.164 -        Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
  55.165 -        assertEquals(st.invoke(null, true, false, 10, 20), 10L, "Take first value");
  55.166 -    }
  55.167 -
  55.168 -    @Test public void secondLong() throws Throwable {
  55.169 -        Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
  55.170 -        assertEquals(st.invoke(null, false, true, 10, 20), 20L, "Take 2nd value");
  55.171 -    }
  55.172 -
  55.173 -    @Test public void bothLong() throws Throwable {
  55.174 -        Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
  55.175 -        assertEquals(st.invoke(null, true, true, 10, 20), 30L, "Take both values");
  55.176 -    }
  55.177 -    
  55.178 -    @Test public void recordError() throws Throwable {
  55.179 -        Method st = methodClass.getMethod("recordError", Object.class);
  55.180 -        assertEquals(st.invoke(methodClass.newInstance(), "Hello"), "Hello", "The same parameter returned");
  55.181 -    }
  55.182 -}
  55.183 \ No newline at end of file
    56.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JsClassLoaderTest.java	Thu Dec 19 17:11:01 2013 +0100
    56.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.3 @@ -1,133 +0,0 @@
    56.4 -/**
    56.5 - * HTML via Java(tm) Language Bindings
    56.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    56.7 - *
    56.8 - * This program is free software: you can redistribute it and/or modify
    56.9 - * it under the terms of the GNU General Public License as published by
   56.10 - * the Free Software Foundation, version 2 of the License.
   56.11 - *
   56.12 - * This program is distributed in the hope that it will be useful,
   56.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   56.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   56.15 - * GNU General Public License for more details. apidesign.org
   56.16 - * designates this particular file as subject to the
   56.17 - * "Classpath" exception as provided by apidesign.org
   56.18 - * in the License file that accompanied this code.
   56.19 - *
   56.20 - * You should have received a copy of the GNU General Public License
   56.21 - * along with this program. Look for COPYING file in the top folder.
   56.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   56.23 - */
   56.24 -package org.apidesign.html.boot.impl;
   56.25 -
   56.26 -import java.io.Closeable;
   56.27 -import java.io.Reader;
   56.28 -import org.apidesign.html.boot.spi.Fn;
   56.29 -import java.net.URL;
   56.30 -import java.net.URLClassLoader;
   56.31 -import java.util.ArrayList;
   56.32 -import java.util.Arrays;
   56.33 -import java.util.Enumeration;
   56.34 -import java.util.List;
   56.35 -import javax.script.Invocable;
   56.36 -import javax.script.ScriptEngine;
   56.37 -import javax.script.ScriptEngineManager;
   56.38 -import javax.script.ScriptException;
   56.39 -import org.testng.annotations.AfterClass;
   56.40 -import org.testng.annotations.BeforeClass;
   56.41 -import org.testng.annotations.BeforeMethod;
   56.42 -
   56.43 -/**
   56.44 - *
   56.45 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   56.46 - */
   56.47 -public class JsClassLoaderTest extends JsClassLoaderBase{
   56.48 -    private static Fn.Presenter loader;
   56.49 -
   56.50 -    @BeforeClass
   56.51 -    public static void setUpClass() throws Exception {
   56.52 -        ScriptEngineManager sem = new ScriptEngineManager();
   56.53 -        final ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
   56.54 -        
   56.55 -        final URL my = JsClassLoaderTest.class.getProtectionDomain().getCodeSource().getLocation();
   56.56 -        ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
   56.57 -        final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
   56.58 -        class MyCL extends JsClassLoader implements Fn.Presenter {
   56.59 -
   56.60 -            public MyCL(ClassLoader parent) {
   56.61 -                super(parent);
   56.62 -            }
   56.63 -            
   56.64 -            @Override
   56.65 -            protected URL findResource(String name) {
   56.66 -                return ul.getResource(name);
   56.67 -            }
   56.68 -            @Override
   56.69 -            public Fn defineFn(String code, String... names) {
   56.70 -                StringBuilder sb = new StringBuilder();
   56.71 -                sb.append("(function() {");
   56.72 -                sb.append("return function(");
   56.73 -                String sep = "";
   56.74 -                for (String n : names) {
   56.75 -                    sb.append(sep);
   56.76 -                    sb.append(n);
   56.77 -                    sep = ", ";
   56.78 -                }
   56.79 -                sb.append(") {");
   56.80 -                sb.append(code);
   56.81 -                sb.append("};");
   56.82 -                sb.append("})()");
   56.83 -                try {
   56.84 -                    final Object val = eng.eval(sb.toString());
   56.85 -                    return new Fn(this) {
   56.86 -                        @Override
   56.87 -                        public Object invoke(Object thiz, Object... args) throws Exception {
   56.88 -                            List<Object> all = new ArrayList<Object>(args.length + 1);
   56.89 -                            all.add(thiz == null ? val : thiz);
   56.90 -                            all.addAll(Arrays.asList(args));
   56.91 -                            Invocable inv = (Invocable)eng;
   56.92 -                            try {
   56.93 -                                Object ret = inv.invokeMethod(val, "call", all.toArray());
   56.94 -                                return val.equals(ret) ? null : ret;
   56.95 -                            } catch (Exception ex) {
   56.96 -                                throw ex;
   56.97 -                            }
   56.98 -                        }
   56.99 -                    };
  56.100 -                } catch (ScriptException ex) {
  56.101 -                    throw new LinkageError("Can't parse: " + sb, ex);
  56.102 -                }
  56.103 -            }
  56.104 -
  56.105 -            @Override
  56.106 -            protected Enumeration<URL> findResources(String name) {
  56.107 -                throw new UnsupportedOperationException();
  56.108 -            }
  56.109 -
  56.110 -            @Override
  56.111 -            public void loadScript(Reader code) throws ScriptException {
  56.112 -                eng.eval(code);
  56.113 -            }
  56.114 -
  56.115 -            @Override
  56.116 -            public void displayPage(URL page, Runnable onPageLoad) {
  56.117 -                throw new UnsupportedOperationException();
  56.118 -            }
  56.119 -        };
  56.120 -        
  56.121 -        MyCL l = new MyCL(parent);
  56.122 -        Closeable close = FnContext.activate(l);
  56.123 -        methodClass = l.loadClass(JsMethods.class.getName());
  56.124 -        close.close();
  56.125 -        loader = l;
  56.126 -    }
  56.127 -    
  56.128 -    @BeforeMethod public void initPresenter() {
  56.129 -        FnContext.currentPresenter(loader);
  56.130 -    }
  56.131 -
  56.132 -    @AfterClass
  56.133 -    public static void cleanUp() {
  56.134 -        methodClass = null;
  56.135 -    }
  56.136 -}
  56.137 \ No newline at end of file
    57.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JsMethods.java	Thu Dec 19 17:11:01 2013 +0100
    57.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.3 @@ -1,107 +0,0 @@
    57.4 -/**
    57.5 - * HTML via Java(tm) Language Bindings
    57.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    57.7 - *
    57.8 - * This program is free software: you can redistribute it and/or modify
    57.9 - * it under the terms of the GNU General Public License as published by
   57.10 - * the Free Software Foundation, version 2 of the License.
   57.11 - *
   57.12 - * This program is distributed in the hope that it will be useful,
   57.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   57.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   57.15 - * GNU General Public License for more details. apidesign.org
   57.16 - * designates this particular file as subject to the
   57.17 - * "Classpath" exception as provided by apidesign.org
   57.18 - * in the License file that accompanied this code.
   57.19 - *
   57.20 - * You should have received a copy of the GNU General Public License
   57.21 - * along with this program. Look for COPYING file in the top folder.
   57.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   57.23 - */
   57.24 -package org.apidesign.html.boot.impl;
   57.25 -
   57.26 -import net.java.html.js.JavaScriptBody;
   57.27 -import net.java.html.js.JavaScriptResource;
   57.28 -
   57.29 -
   57.30 -/**
   57.31 - *
   57.32 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   57.33 - */
   57.34 -@JavaScriptResource("jsmethods.js")
   57.35 -public class JsMethods {
   57.36 -    private Object value;
   57.37 -    
   57.38 -    @JavaScriptBody(args = {}, body = "return 42;")
   57.39 -    public static Object fortyTwo() {
   57.40 -        return -42;
   57.41 -    }
   57.42 -    
   57.43 -    @JavaScriptBody(args = {"x", "y" }, body = "return x + y;")
   57.44 -    public static native int plus(int x, int y);
   57.45 -    
   57.46 -    @JavaScriptBody(args = {"x"}, body = "return x;")
   57.47 -    public static native int plus(int x);
   57.48 -    
   57.49 -    @JavaScriptBody(args = {}, body = "return this;")
   57.50 -    public static native Object staticThis();
   57.51 -    
   57.52 -    @JavaScriptBody(args = {}, body = "return this;")
   57.53 -    public native Object getThis();
   57.54 -    @JavaScriptBody(args = {"x"}, body = "return x;")
   57.55 -    public native int plusInst(int x);
   57.56 -    
   57.57 -    @JavaScriptBody(args = {}, body = "return true;")
   57.58 -    public static boolean truth() {
   57.59 -        return false;
   57.60 -    }
   57.61 -    
   57.62 -    @JavaScriptBody(args = { "r" }, javacall=true, body = "r.@java.lang.Runnable::run()();")
   57.63 -    public static native void callback(Runnable r);
   57.64 -    
   57.65 -    @JavaScriptBody(args = { "at", "arr" }, javacall = true, body =
   57.66 -          "var a = 0;\n"
   57.67 -        + "for (var i = 0; i < arr.length; i++) {\n"
   57.68 -        + "  a = at.@org.apidesign.html.boot.impl.Arithm::sumTwo(II)(a, arr[i]);\n"
   57.69 -        + "}\n"
   57.70 -        + "return a;"
   57.71 -    )
   57.72 -    private static native int sumArr(Arithm at, int... arr);
   57.73 -    
   57.74 -    public static int sumArr(int... arr) {
   57.75 -        return sumArr(new Arithm(), arr);
   57.76 -    }
   57.77 -    
   57.78 -    @JavaScriptBody(args = { "x", "y" }, body = "return mul(x, y);")
   57.79 -    public static native int useExternalMul(int x, int y);
   57.80 -    
   57.81 -    @JavaScriptBody(args = { "m" }, javacall = true, body = "return m.@org.apidesign.html.boot.impl.JsMethods::getThis()();")
   57.82 -    public static native JsMethods returnYourSelf(JsMethods m);
   57.83 -    
   57.84 -    @JavaScriptBody(args = { "x", "y" }, javacall = true, body = "return @org.apidesign.html.boot.impl.JsMethods::useExternalMul(II)(x, y);")
   57.85 -    public static native int staticCallback(int x, int y);
   57.86 -
   57.87 -    @JavaScriptBody(args = { "v" }, javacall = true, body = "return @java.lang.Integer::parseInt(Ljava/lang/String;)(v);")
   57.88 -    public static native int parseInt(String v);
   57.89 -    
   57.90 -    @JavaScriptBody(args = { "useA", "useB", "a", "b" }, body = "var l = 0;"
   57.91 -        + "if (useA) l += a;\n"
   57.92 -        + "if (useB) l += b;\n"
   57.93 -        + "return l;\n"
   57.94 -    )
   57.95 -    public static native long chooseLong(boolean useA, boolean useB, long a, long b);
   57.96 -    
   57.97 -    protected void onError(Object o) throws Exception {
   57.98 -        value = o;
   57.99 -    }
  57.100 -    
  57.101 -    Object getError() {
  57.102 -        return value;
  57.103 -    }
  57.104 -    
  57.105 -    @JavaScriptBody(args = { "err" }, javacall = true, body = 
  57.106 -        "this.@org.apidesign.html.boot.impl.JsMethods::onError(Ljava/lang/Object;)(err);"
  57.107 -      + "return this.@org.apidesign.html.boot.impl.JsMethods::getError()();"
  57.108 -    )
  57.109 -    public native Object recordError(Object err);
  57.110 -}
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/Arithm.java	Tue Jan 07 08:21:57 2014 +0100
    58.3 @@ -0,0 +1,53 @@
    58.4 +/**
    58.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    58.6 + *
    58.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    58.8 + *
    58.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   58.10 + * Other names may be trademarks of their respective owners.
   58.11 + *
   58.12 + * The contents of this file are subject to the terms of either the GNU
   58.13 + * General Public License Version 2 only ("GPL") or the Common
   58.14 + * Development and Distribution License("CDDL") (collectively, the
   58.15 + * "License"). You may not use this file except in compliance with the
   58.16 + * License. You can obtain a copy of the License at
   58.17 + * http://www.netbeans.org/cddl-gplv2.html
   58.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   58.19 + * specific language governing permissions and limitations under the
   58.20 + * License.  When distributing the software, include this License Header
   58.21 + * Notice in each file and include the License file at
   58.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   58.23 + * particular file as subject to the "Classpath" exception as provided
   58.24 + * by Oracle in the GPL Version 2 section of the License file that
   58.25 + * accompanied this code. If applicable, add the following below the
   58.26 + * License Header, with the fields enclosed by brackets [] replaced by
   58.27 + * your own identifying information:
   58.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   58.29 + *
   58.30 + * Contributor(s):
   58.31 + *
   58.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   58.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   58.34 + *
   58.35 + * If you wish your version of this file to be governed by only the CDDL
   58.36 + * or only the GPL Version 2, indicate your decision by adding
   58.37 + * "[Contributor] elects to include this software in this distribution
   58.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   58.39 + * single choice of license, a recipient has the option to distribute
   58.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   58.41 + * to extend the choice of license to its licensees as provided above.
   58.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   58.43 + * Version 2 license, then the option applies only if the new code is
   58.44 + * made subject to such option by the copyright holder.
   58.45 + */
   58.46 +package org.netbeans.html.boot.impl;
   58.47 +
   58.48 +/**
   58.49 + *
   58.50 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   58.51 + */
   58.52 +public class Arithm {
   58.53 +    public int sumTwo(int a, int b) {
   58.54 +        return a + b;
   58.55 +    }
   58.56 +}
    59.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/Compile.java	Tue Jan 07 08:21:57 2014 +0100
    59.3 @@ -0,0 +1,291 @@
    59.4 +/**
    59.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    59.6 + *
    59.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    59.8 + *
    59.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   59.10 + * Other names may be trademarks of their respective owners.
   59.11 + *
   59.12 + * The contents of this file are subject to the terms of either the GNU
   59.13 + * General Public License Version 2 only ("GPL") or the Common
   59.14 + * Development and Distribution License("CDDL") (collectively, the
   59.15 + * "License"). You may not use this file except in compliance with the
   59.16 + * License. You can obtain a copy of the License at
   59.17 + * http://www.netbeans.org/cddl-gplv2.html
   59.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   59.19 + * specific language governing permissions and limitations under the
   59.20 + * License.  When distributing the software, include this License Header
   59.21 + * Notice in each file and include the License file at
   59.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   59.23 + * particular file as subject to the "Classpath" exception as provided
   59.24 + * by Oracle in the GPL Version 2 section of the License file that
   59.25 + * accompanied this code. If applicable, add the following below the
   59.26 + * License Header, with the fields enclosed by brackets [] replaced by
   59.27 + * your own identifying information:
   59.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   59.29 + *
   59.30 + * Contributor(s):
   59.31 + *
   59.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   59.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   59.34 + *
   59.35 + * If you wish your version of this file to be governed by only the CDDL
   59.36 + * or only the GPL Version 2, indicate your decision by adding
   59.37 + * "[Contributor] elects to include this software in this distribution
   59.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   59.39 + * single choice of license, a recipient has the option to distribute
   59.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   59.41 + * to extend the choice of license to its licensees as provided above.
   59.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   59.43 + * Version 2 license, then the option applies only if the new code is
   59.44 + * made subject to such option by the copyright holder.
   59.45 + */
   59.46 +package org.netbeans.html.boot.impl;
   59.47 +
   59.48 +import java.io.ByteArrayInputStream;
   59.49 +import java.io.ByteArrayOutputStream;
   59.50 +import java.io.IOException;
   59.51 +import java.io.InputStream;
   59.52 +import java.io.OutputStream;
   59.53 +import java.net.URI;
   59.54 +import java.net.URISyntaxException;
   59.55 +import java.util.ArrayList;
   59.56 +import java.util.Arrays;
   59.57 +import java.util.HashMap;
   59.58 +import java.util.List;
   59.59 +import java.util.Locale;
   59.60 +import java.util.Map;
   59.61 +import java.util.regex.Matcher;
   59.62 +import java.util.regex.Pattern;
   59.63 +import javax.tools.Diagnostic;
   59.64 +import javax.tools.DiagnosticListener;
   59.65 +import javax.tools.FileObject;
   59.66 +import javax.tools.ForwardingJavaFileManager;
   59.67 +import javax.tools.JavaFileManager;
   59.68 +import javax.tools.JavaFileObject;
   59.69 +import javax.tools.JavaFileObject.Kind;
   59.70 +import javax.tools.SimpleJavaFileObject;
   59.71 +import javax.tools.StandardJavaFileManager;
   59.72 +import javax.tools.StandardLocation;
   59.73 +import javax.tools.ToolProvider;
   59.74 +import static org.testng.Assert.assertTrue;
   59.75 +import static org.testng.Assert.assertFalse;
   59.76 +import static org.testng.Assert.fail;
   59.77 +
   59.78 +/**
   59.79 + *
   59.80 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   59.81 + */
   59.82 +final class Compile implements DiagnosticListener<JavaFileObject> {
   59.83 +    private final List<Diagnostic<? extends JavaFileObject>> errors = 
   59.84 +            new ArrayList<Diagnostic<? extends JavaFileObject>>();
   59.85 +    private final Map<String, byte[]> classes;
   59.86 +    private final String pkg;
   59.87 +    private final String cls;
   59.88 +    private final String html;
   59.89 +    private final String sourceLevel;
   59.90 +
   59.91 +    private Compile(String html, String code, String sl) throws IOException {
   59.92 +        this.pkg = findPkg(code);
   59.93 +        this.cls = findCls(code);
   59.94 +        this.html = html;
   59.95 +        this.sourceLevel = sl;
   59.96 +        classes = compile(html, code);
   59.97 +    }
   59.98 +
   59.99 +    /** Performs compilation of given HTML page and associated Java code
  59.100 +     */
  59.101 +    public static Compile create(String html, String code) throws IOException {
  59.102 +        return create(html, code, "1.7");
  59.103 +    }
  59.104 +    static Compile create(String html, String code, String sourceLevel) throws IOException {
  59.105 +        return new Compile(html, code, sourceLevel);
  59.106 +    }
  59.107 +    
  59.108 +    /** Checks for given class among compiled resources */
  59.109 +    public byte[] get(String res) {
  59.110 +        return classes.get(res);
  59.111 +    }
  59.112 +    
  59.113 +    /** Obtains errors created during compilation.
  59.114 +     */
  59.115 +    public List<Diagnostic<? extends JavaFileObject>> getErrors() {
  59.116 +        List<Diagnostic<? extends JavaFileObject>> err;
  59.117 +        err = new ArrayList<Diagnostic<? extends JavaFileObject>>();
  59.118 +        for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
  59.119 +            if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
  59.120 +                err.add(diagnostic);
  59.121 +            }
  59.122 +        }
  59.123 +        return err;
  59.124 +    }
  59.125 +    
  59.126 +    private Map<String, byte[]> compile(final String html, final String code) throws IOException {
  59.127 +        StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
  59.128 +
  59.129 +        final Map<String, ByteArrayOutputStream> class2BAOS;
  59.130 +        class2BAOS = new HashMap<String, ByteArrayOutputStream>();
  59.131 +
  59.132 +        JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
  59.133 +            @Override
  59.134 +            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  59.135 +                return code;
  59.136 +            }
  59.137 +        };
  59.138 +        final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
  59.139 +            @Override
  59.140 +            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  59.141 +                return html;
  59.142 +            }
  59.143 +
  59.144 +            @Override
  59.145 +            public InputStream openInputStream() throws IOException {
  59.146 +                return new ByteArrayInputStream(html.getBytes());
  59.147 +            }
  59.148 +        };
  59.149 +        
  59.150 +        final URI scratch;
  59.151 +        try {
  59.152 +            scratch = new URI("mem://mem3");
  59.153 +        } catch (URISyntaxException ex) {
  59.154 +            throw new IOException(ex);
  59.155 +        }
  59.156 +        
  59.157 +        JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
  59.158 +            @Override
  59.159 +            public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
  59.160 +                if (kind  == Kind.CLASS) {
  59.161 +                    final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
  59.162 +
  59.163 +                    class2BAOS.put(className.replace('.', '/') + ".class", buffer);
  59.164 +                    return new SimpleJavaFileObject(sibling.toUri(), kind) {
  59.165 +                        @Override
  59.166 +                        public OutputStream openOutputStream() throws IOException {
  59.167 +                            return buffer;
  59.168 +                        }
  59.169 +                    };
  59.170 +                }
  59.171 +                
  59.172 +                if (kind == Kind.SOURCE) {
  59.173 +                    final String n = className.replace('.', '/') + ".java";
  59.174 +                    final URI un;
  59.175 +                    try {
  59.176 +                        un = new URI("mem://" + n);
  59.177 +                    } catch (URISyntaxException ex) {
  59.178 +                        throw new IOException(ex);
  59.179 +                    }
  59.180 +                    return new VirtFO(un/*sibling.toUri()*/, kind, n);
  59.181 +                }
  59.182 +                
  59.183 +                throw new IllegalStateException();
  59.184 +            }
  59.185 +
  59.186 +            @Override
  59.187 +            public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
  59.188 +                if (location == StandardLocation.SOURCE_PATH) {
  59.189 +                    if (packageName.equals(pkg)) {
  59.190 +                        return htmlFile;
  59.191 +                    }
  59.192 +                }
  59.193 +                
  59.194 +                return null;
  59.195 +            }
  59.196 +
  59.197 +            @Override
  59.198 +            public boolean isSameFile(FileObject a, FileObject b) {
  59.199 +                if (a instanceof VirtFO && b instanceof VirtFO) {
  59.200 +                    return ((VirtFO)a).getName().equals(((VirtFO)b).getName());
  59.201 +                }
  59.202 +                
  59.203 +                return super.isSameFile(a, b);
  59.204 +            }
  59.205 +
  59.206 +            class VirtFO extends SimpleJavaFileObject {
  59.207 +
  59.208 +                private final String n;
  59.209 +
  59.210 +                public VirtFO(URI uri, Kind kind, String n) {
  59.211 +                    super(uri, kind);
  59.212 +                    this.n = n;
  59.213 +                }
  59.214 +                private final ByteArrayOutputStream data = new ByteArrayOutputStream();
  59.215 +
  59.216 +                @Override
  59.217 +                public OutputStream openOutputStream() throws IOException {
  59.218 +                    return data;
  59.219 +                }
  59.220 +
  59.221 +                @Override
  59.222 +                public String getName() {
  59.223 +                    return n;
  59.224 +                }
  59.225 +
  59.226 +                @Override
  59.227 +                public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  59.228 +                    data.close();
  59.229 +                    return new String(data.toByteArray());
  59.230 +                }
  59.231 +            }
  59.232 +        };
  59.233 +
  59.234 +        ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", sourceLevel, "-target", "1.7"), null, Arrays.asList(file)).call();
  59.235 +
  59.236 +        Map<String, byte[]> result = new HashMap<String, byte[]>();
  59.237 +
  59.238 +        for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
  59.239 +            result.put(e.getKey(), e.getValue().toByteArray());
  59.240 +        }
  59.241 +
  59.242 +        return result;
  59.243 +    }
  59.244 +
  59.245 +
  59.246 +    @Override
  59.247 +    public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
  59.248 +        errors.add(diagnostic);
  59.249 +    }
  59.250 +    private static String findPkg(String java) throws IOException {
  59.251 +        Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
  59.252 +        Matcher m = p.matcher(java);
  59.253 +        if (!m.find()) {
  59.254 +            throw new IOException("Can't find package declaration in the java file");
  59.255 +        }
  59.256 +        String pkg = m.group(1);
  59.257 +        return pkg;
  59.258 +    }
  59.259 +    private static String findCls(String java) throws IOException {
  59.260 +        Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
  59.261 +        Matcher m = p.matcher(java);
  59.262 +        if (!m.find()) {
  59.263 +            throw new IOException("Can't find package declaration in the java file");
  59.264 +        }
  59.265 +        String cls = m.group(1);
  59.266 +        return cls;
  59.267 +    }
  59.268 +
  59.269 +    String getHtml() {
  59.270 +        String fqn = "'" + pkg + '.' + cls + "'";
  59.271 +        return html.replace("'${fqn}'", fqn);
  59.272 +    }
  59.273 +    void assertErrors() {
  59.274 +        assertFalse(getErrors().isEmpty(), "There are supposed to be some errors");
  59.275 +    }
  59.276 +
  59.277 +    void assertError(String expMsg) {
  59.278 +        StringBuilder sb = new StringBuilder();
  59.279 +        sb.append("Can't find ").append(expMsg).append(" among:");
  59.280 +        for (Diagnostic<? extends JavaFileObject> e : errors) {
  59.281 +            String msg = e.getMessage(Locale.US);
  59.282 +            if (msg.contains(expMsg)) {
  59.283 +                return;
  59.284 +            }
  59.285 +            sb.append("\n");
  59.286 +            sb.append(msg);
  59.287 +        }
  59.288 +        fail(sb.toString());
  59.289 +    }
  59.290 +
  59.291 +    void assertNoErrors() {
  59.292 +        assertTrue(getErrors().isEmpty(), "No errors expected: " + getErrors());
  59.293 +    }
  59.294 +}
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/FnTest.java	Tue Jan 07 08:21:57 2014 +0100
    60.3 @@ -0,0 +1,148 @@
    60.4 +/**
    60.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    60.6 + *
    60.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    60.8 + *
    60.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   60.10 + * Other names may be trademarks of their respective owners.
   60.11 + *
   60.12 + * The contents of this file are subject to the terms of either the GNU
   60.13 + * General Public License Version 2 only ("GPL") or the Common
   60.14 + * Development and Distribution License("CDDL") (collectively, the
   60.15 + * "License"). You may not use this file except in compliance with the
   60.16 + * License. You can obtain a copy of the License at
   60.17 + * http://www.netbeans.org/cddl-gplv2.html
   60.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   60.19 + * specific language governing permissions and limitations under the
   60.20 + * License.  When distributing the software, include this License Header
   60.21 + * Notice in each file and include the License file at
   60.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   60.23 + * particular file as subject to the "Classpath" exception as provided
   60.24 + * by Oracle in the GPL Version 2 section of the License file that
   60.25 + * accompanied this code. If applicable, add the following below the
   60.26 + * License Header, with the fields enclosed by brackets [] replaced by
   60.27 + * your own identifying information:
   60.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   60.29 + *
   60.30 + * Contributor(s):
   60.31 + *
   60.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   60.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   60.34 + *
   60.35 + * If you wish your version of this file to be governed by only the CDDL
   60.36 + * or only the GPL Version 2, indicate your decision by adding
   60.37 + * "[Contributor] elects to include this software in this distribution
   60.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   60.39 + * single choice of license, a recipient has the option to distribute
   60.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   60.41 + * to extend the choice of license to its licensees as provided above.
   60.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   60.43 + * Version 2 license, then the option applies only if the new code is
   60.44 + * made subject to such option by the copyright holder.
   60.45 + */
   60.46 +package org.netbeans.html.boot.impl;
   60.47 +
   60.48 +import java.io.Closeable;
   60.49 +import java.io.Reader;
   60.50 +import java.net.URL;
   60.51 +import java.net.URLClassLoader;
   60.52 +import java.util.ArrayList;
   60.53 +import java.util.Arrays;
   60.54 +import java.util.Collection;
   60.55 +import java.util.List;
   60.56 +import javax.script.Invocable;
   60.57 +import javax.script.ScriptEngine;
   60.58 +import javax.script.ScriptEngineManager;
   60.59 +import javax.script.ScriptException;
   60.60 +import org.apidesign.html.boot.spi.Fn;
   60.61 +import org.testng.annotations.BeforeClass;
   60.62 +import org.testng.annotations.BeforeMethod;
   60.63 +
   60.64 +/**
   60.65 + *
   60.66 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   60.67 + */
   60.68 +public class FnTest extends JsClassLoaderBase {
   60.69 +    private static Fn.Presenter presenter;
   60.70 +    
   60.71 +    public FnTest() {
   60.72 +    }
   60.73 +
   60.74 +    @BeforeClass
   60.75 +    public static void createClassLoader() throws Exception {
   60.76 +        ScriptEngineManager sem = new ScriptEngineManager();
   60.77 +        final ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
   60.78 +        
   60.79 +        final URL my = FnTest.class.getProtectionDomain().getCodeSource().getLocation();
   60.80 +        ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
   60.81 +        final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
   60.82 +        
   60.83 +        class Impl implements FindResources, Fn.Presenter {
   60.84 +            @Override
   60.85 +            public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough) {
   60.86 +                URL u = ul.findResource(path);
   60.87 +                if (u != null) {
   60.88 +                    results.add(u);
   60.89 +                }
   60.90 +            }
   60.91 +
   60.92 +            @Override
   60.93 +            public Fn defineFn(String code, String... names) {
   60.94 +                StringBuilder sb = new StringBuilder();
   60.95 +                sb.append("(function() {");
   60.96 +                sb.append("return function(");
   60.97 +                String sep = "";
   60.98 +                for (String n : names) {
   60.99 +                    sb.append(sep);
  60.100 +                    sb.append(n);
  60.101 +                    sep = ", ";
  60.102 +                }
  60.103 +                sb.append(") {");
  60.104 +                sb.append(code);
  60.105 +                sb.append("};");
  60.106 +                sb.append("})()");
  60.107 +                try {
  60.108 +                    final Object val = eng.eval(sb.toString());
  60.109 +                    return new Fn(this) {
  60.110 +                        @Override
  60.111 +                        public Object invoke(Object thiz, Object... args) throws Exception {
  60.112 +                            List<Object> all = new ArrayList<Object>(args.length + 1);
  60.113 +                            all.add(thiz == null ? val : thiz);
  60.114 +                            all.addAll(Arrays.asList(args));
  60.115 +                            Invocable inv = (Invocable)eng;
  60.116 +                            try {
  60.117 +                                Object ret = inv.invokeMethod(val, "call", all.toArray());
  60.118 +                                return val.equals(ret) ? null : ret;
  60.119 +                            } catch (ScriptException ex) {
  60.120 +                                throw ex;
  60.121 +                            }
  60.122 +                        }
  60.123 +                    };
  60.124 +                } catch (ScriptException ex) {
  60.125 +                    throw new LinkageError("Can't parse: " + sb, ex);
  60.126 +                }
  60.127 +            }
  60.128 +
  60.129 +            @Override
  60.130 +            public void displayPage(URL resource, Runnable r) {
  60.131 +                throw new UnsupportedOperationException();
  60.132 +            }
  60.133 +
  60.134 +            @Override
  60.135 +            public void loadScript(Reader code) throws Exception {
  60.136 +                eng.eval(code);
  60.137 +            }
  60.138 +        }
  60.139 +        Impl impl = new Impl();
  60.140 +        ClassLoader loader = FnUtils.newLoader(impl, impl, parent);
  60.141 +        presenter = impl;
  60.142 +        
  60.143 +        Closeable close = FnContext.activate(impl);
  60.144 +        methodClass = loader.loadClass(JsMethods.class.getName());
  60.145 +        close.close();
  60.146 +    }
  60.147 +
  60.148 +    @BeforeMethod public void initPresenter() {
  60.149 +        FnContext.currentPresenter(presenter);
  60.150 +    }
  60.151 +}
    61.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/JavaScriptProcesorTest.java	Tue Jan 07 08:21:57 2014 +0100
    61.3 @@ -0,0 +1,129 @@
    61.4 +/**
    61.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    61.6 + *
    61.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    61.8 + *
    61.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   61.10 + * Other names may be trademarks of their respective owners.
   61.11 + *
   61.12 + * The contents of this file are subject to the terms of either the GNU
   61.13 + * General Public License Version 2 only ("GPL") or the Common
   61.14 + * Development and Distribution License("CDDL") (collectively, the
   61.15 + * "License"). You may not use this file except in compliance with the
   61.16 + * License. You can obtain a copy of the License at
   61.17 + * http://www.netbeans.org/cddl-gplv2.html
   61.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   61.19 + * specific language governing permissions and limitations under the
   61.20 + * License.  When distributing the software, include this License Header
   61.21 + * Notice in each file and include the License file at
   61.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   61.23 + * particular file as subject to the "Classpath" exception as provided
   61.24 + * by Oracle in the GPL Version 2 section of the License file that
   61.25 + * accompanied this code. If applicable, add the following below the
   61.26 + * License Header, with the fields enclosed by brackets [] replaced by
   61.27 + * your own identifying information:
   61.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   61.29 + *
   61.30 + * Contributor(s):
   61.31 + *
   61.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   61.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   61.34 + *
   61.35 + * If you wish your version of this file to be governed by only the CDDL
   61.36 + * or only the GPL Version 2, indicate your decision by adding
   61.37 + * "[Contributor] elects to include this software in this distribution
   61.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   61.39 + * single choice of license, a recipient has the option to distribute
   61.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   61.41 + * to extend the choice of license to its licensees as provided above.
   61.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   61.43 + * Version 2 license, then the option applies only if the new code is
   61.44 + * made subject to such option by the copyright holder.
   61.45 + */
   61.46 +package org.netbeans.html.boot.impl;
   61.47 +
   61.48 +import java.io.IOException;
   61.49 +import java.lang.reflect.Field;
   61.50 +import java.lang.reflect.Method;
   61.51 +import static org.testng.Assert.assertEquals;
   61.52 +import static org.testng.Assert.assertTrue;
   61.53 +import org.testng.annotations.Test;
   61.54 +
   61.55 +/**
   61.56 + *
   61.57 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   61.58 + */
   61.59 +public class JavaScriptProcesorTest {
   61.60 +    
   61.61 +    @Test public void detectCallbackToNonExistingClass() throws IOException {
   61.62 +        String code = "package x.y.z;\n"
   61.63 +            + "import net.java.html.js.JavaScriptBody;\n"
   61.64 +            + "class X {\n"
   61.65 +            + "  @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
   61.66 +            + "    \"r.@java.lang.Runable::run()();\"\n" // typo
   61.67 +            + "  )\n"
   61.68 +            + "  private static native void callback(Runnable r);\n"
   61.69 +            + "}\n";
   61.70 +        
   61.71 +        Compile c = Compile.create("", code);
   61.72 +        c.assertErrors();
   61.73 +        c.assertError("java.lang.Runable"); // typo
   61.74 +    }
   61.75 +
   61.76 +    @Test public void detectCallbackToNonExistingMethod() throws IOException {
   61.77 +        String code = "package x.y.z;\n"
   61.78 +            + "import net.java.html.js.JavaScriptBody;\n"
   61.79 +            + "class X {\n"
   61.80 +            + "  @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
   61.81 +            + "    \"r.@java.lang.Runnable::cancel()();\"\n"
   61.82 +            + "  )\n"
   61.83 +            + "  private static native void callback(Runnable r);\n"
   61.84 +            + "}\n";
   61.85 +        
   61.86 +        Compile c = Compile.create("", code);
   61.87 +        c.assertErrors();
   61.88 +        c.assertError("method cancel");
   61.89 +    }
   61.90 +
   61.91 +    @Test public void detectCallbackToNonExistingParams() throws IOException {
   61.92 +        String code = "package x.y.z;\n"
   61.93 +            + "import net.java.html.js.JavaScriptBody;\n"
   61.94 +            + "class X {\n"
   61.95 +            + "  @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
   61.96 +            + "    \"r.@java.lang.Runnable::run(I)(10);\"\n"
   61.97 +            + "  )\n"
   61.98 +            + "  private static native void callback(Runnable r);\n"
   61.99 +            + "}\n";
  61.100 +        
  61.101 +        Compile c = Compile.create("", code);
  61.102 +        c.assertErrors();
  61.103 +        c.assertError("wrong parameters: (I)");
  61.104 +    }
  61.105 +
  61.106 +    @Test public void objectTypeParamsAreOK() throws IOException {
  61.107 +        String code = "package x.y.z;\n"
  61.108 +            + "import net.java.html.js.JavaScriptBody;\n"
  61.109 +            + "class X {\n"
  61.110 +            + "  @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
  61.111 +            + "    \"r.@java.lang.Object::equals(Ljava/lang/Object;)(null);\"\n"
  61.112 +            + "  )\n"
  61.113 +            + "  private static native void testEqual(Object r);\n"
  61.114 +            + "}\n";
  61.115 +        
  61.116 +        Compile c = Compile.create("", code);
  61.117 +        c.assertNoErrors();
  61.118 +    }
  61.119 +    
  61.120 +    @Test public void generatesCallbacksThatReturnObject() throws Exception {
  61.121 +        Class<?> callbacksForTestPkg = Class.forName("org.netbeans.html.boot.impl.$JsCallbacks$");
  61.122 +        Method m = callbacksForTestPkg.getDeclaredMethod("java_lang_Runnable$run$", Runnable.class);
  61.123 +        assertEquals(m.getReturnType(), Object.class, "All methods always return object");
  61.124 +    }
  61.125 +    
  61.126 +    @Test public void hasInstanceField() throws Exception {
  61.127 +        Class<?> callbacksForTestPkg = Class.forName("org.netbeans.html.boot.impl.$JsCallbacks$");
  61.128 +        Field f = callbacksForTestPkg.getDeclaredField("VM");
  61.129 +        f.setAccessible(true);
  61.130 +        assertTrue(callbacksForTestPkg.isInstance(f.get(null)), "Singleton field VM");
  61.131 +    }
  61.132 +}
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/JsClassLoaderBase.java	Tue Jan 07 08:21:57 2014 +0100
    62.3 @@ -0,0 +1,201 @@
    62.4 +/**
    62.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    62.6 + *
    62.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    62.8 + *
    62.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   62.10 + * Other names may be trademarks of their respective owners.
   62.11 + *
   62.12 + * The contents of this file are subject to the terms of either the GNU
   62.13 + * General Public License Version 2 only ("GPL") or the Common
   62.14 + * Development and Distribution License("CDDL") (collectively, the
   62.15 + * "License"). You may not use this file except in compliance with the
   62.16 + * License. You can obtain a copy of the License at
   62.17 + * http://www.netbeans.org/cddl-gplv2.html
   62.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   62.19 + * specific language governing permissions and limitations under the
   62.20 + * License.  When distributing the software, include this License Header
   62.21 + * Notice in each file and include the License file at
   62.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   62.23 + * particular file as subject to the "Classpath" exception as provided
   62.24 + * by Oracle in the GPL Version 2 section of the License file that
   62.25 + * accompanied this code. If applicable, add the following below the
   62.26 + * License Header, with the fields enclosed by brackets [] replaced by
   62.27 + * your own identifying information:
   62.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   62.29 + *
   62.30 + * Contributor(s):
   62.31 + *
   62.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   62.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   62.34 + *
   62.35 + * If you wish your version of this file to be governed by only the CDDL
   62.36 + * or only the GPL Version 2, indicate your decision by adding
   62.37 + * "[Contributor] elects to include this software in this distribution
   62.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   62.39 + * single choice of license, a recipient has the option to distribute
   62.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   62.41 + * to extend the choice of license to its licensees as provided above.
   62.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   62.43 + * Version 2 license, then the option applies only if the new code is
   62.44 + * made subject to such option by the copyright holder.
   62.45 + */
   62.46 +package org.netbeans.html.boot.impl;
   62.47 +
   62.48 +import java.lang.reflect.InvocationTargetException;
   62.49 +import java.lang.reflect.Method;
   62.50 +import java.lang.reflect.Modifier;
   62.51 +import static org.testng.Assert.*;
   62.52 +import org.testng.annotations.BeforeMethod;
   62.53 +import org.testng.annotations.Test;
   62.54 +
   62.55 +/**
   62.56 + *
   62.57 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   62.58 + */
   62.59 +public class JsClassLoaderBase {
   62.60 +    protected static Class<?> methodClass;
   62.61 +    
   62.62 +    public JsClassLoaderBase() {
   62.63 +    }
   62.64 +    
   62.65 +    @BeforeMethod
   62.66 +    public void assertClassDefined() {
   62.67 +        assertNotNull(methodClass, "BeforeClass set up code should provide methodClass");
   62.68 +    }
   62.69 +
   62.70 +    @Test public void noParamMethod() throws Throwable {
   62.71 +        Method plus = methodClass.getMethod("fortyTwo");
   62.72 +        try {
   62.73 +            final Object val = plus.invoke(null);
   62.74 +            assertTrue(val instanceof Number, "A number returned " + val);
   62.75 +            assertEquals(((Number)val).intValue(), 42);
   62.76 +        } catch (InvocationTargetException ex) {
   62.77 +            throw ex.getTargetException();
   62.78 +        }
   62.79 +    }
   62.80 +    
   62.81 +    @Test public void testExecuteScript() throws Throwable {
   62.82 +        Method plus = methodClass.getMethod("plus", int.class, int.class);
   62.83 +        try {
   62.84 +            assertEquals(plus.invoke(null, 10, 20), 30);
   62.85 +        } catch (InvocationTargetException ex) {
   62.86 +            throw ex.getTargetException();
   62.87 +        }
   62.88 +    }
   62.89 +
   62.90 +    @Test public void overloadedMethod() throws Throwable {
   62.91 +        Method plus = methodClass.getMethod("plus", int.class);
   62.92 +        try {
   62.93 +            assertEquals(plus.invoke(null, 10), 10);
   62.94 +        } catch (InvocationTargetException ex) {
   62.95 +            throw ex.getTargetException();
   62.96 +        }
   62.97 +    }
   62.98 +    
   62.99 +    @Test public void instanceMethod() throws Throwable {
  62.100 +        Method plus = methodClass.getMethod("plusInst", int.class);
  62.101 +        Object inst = methodClass.newInstance();
  62.102 +        try {
  62.103 +            assertEquals(plus.invoke(inst, 10), 10);
  62.104 +        } catch (InvocationTargetException ex) {
  62.105 +            throw ex.getTargetException();
  62.106 +        }
  62.107 +    }
  62.108 +    
  62.109 +    @Test public void staticThis() throws Throwable {
  62.110 +        Method st = methodClass.getMethod("staticThis");
  62.111 +        try {
  62.112 +            assertNull(st.invoke(null));
  62.113 +        } catch (InvocationTargetException ex) {
  62.114 +            throw ex.getTargetException();
  62.115 +        }
  62.116 +    }
  62.117 +
  62.118 +    @Test public void getThis() throws Throwable {
  62.119 +        Object th = methodClass.newInstance();
  62.120 +        Method st = methodClass.getMethod("getThis");
  62.121 +        try {
  62.122 +            assertEquals(st.invoke(th), th);
  62.123 +        } catch (InvocationTargetException ex) {
  62.124 +            throw ex.getTargetException();
  62.125 +        }
  62.126 +    }
  62.127 +    
  62.128 +    @Test public void truth() throws Throwable {
  62.129 +        Method st = methodClass.getMethod("truth");
  62.130 +        assertTrue((st.getModifiers() & Modifier.STATIC) != 0, "Is static");
  62.131 +        assertEquals(st.invoke(null), Boolean.TRUE, "Can return boolean");
  62.132 +    }
  62.133 +    
  62.134 +    @Test public void callback() throws Throwable {
  62.135 +        class R implements Runnable {
  62.136 +            int cnt;
  62.137 +            
  62.138 +            @Override
  62.139 +            public void run() {
  62.140 +                cnt++;
  62.141 +            }
  62.142 +        }
  62.143 +        R r = new R();
  62.144 +        
  62.145 +        Method inc = methodClass.getMethod("callback", Runnable.class);
  62.146 +        inc.invoke(null, r);
  62.147 +        
  62.148 +        assertEquals(r.cnt, 1, "Callback happened");
  62.149 +    }
  62.150 +    
  62.151 +    @Test public void sumArray() throws Throwable {
  62.152 +        Method st = methodClass.getMethod("sumArr", int[].class);
  62.153 +        assertEquals(st.invoke(null, new int[] { 1, 2, 3 }), 6, "1+2+3 is six");
  62.154 +    }
  62.155 +    
  62.156 +    @Test public void javaScriptResource() throws Throwable {
  62.157 +        try {
  62.158 +            Method st = methodClass.getMethod("useExternalMul", int.class, int.class);
  62.159 +            assertEquals(st.invoke(null, 6, 7), 42, "Meaning of JavaScript?");
  62.160 +        } catch (InvocationTargetException ex) {
  62.161 +            throw ex.getTargetException();
  62.162 +        }
  62.163 +    }
  62.164 +    
  62.165 +    @Test public void callJavaScriptMethodOnOwnClass() throws Throwable {
  62.166 +        try {
  62.167 +            Object thiz = methodClass.newInstance();
  62.168 +            Method st = methodClass.getMethod("returnYourSelf", methodClass);
  62.169 +            assertEquals(st.invoke(null, thiz), thiz, "Returns this");
  62.170 +        } catch (InvocationTargetException ex) {
  62.171 +            throw ex.getTargetException();
  62.172 +        }
  62.173 +    }
  62.174 +    
  62.175 +    @Test public void callStaticJavaMethod() throws Throwable {
  62.176 +        Method st = methodClass.getMethod("staticCallback", int.class, int.class);
  62.177 +        assertEquals(st.invoke(null, 6, 7), 42, "Meaning of JavaScript?");
  62.178 +    }
  62.179 +
  62.180 +    @Test public void callStaticStringParamMethod() throws Throwable {
  62.181 +        Method st = methodClass.getMethod("parseInt", String.class);
  62.182 +        assertEquals(st.invoke(null, "42"), 42, "Meaning of JavaScript?");
  62.183 +    }
  62.184 +    
  62.185 +    @Test public void firstLong() throws Throwable {
  62.186 +        Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
  62.187 +        assertEquals(st.invoke(null, true, false, 10, 20), 10L, "Take first value");
  62.188 +    }
  62.189 +
  62.190 +    @Test public void secondLong() throws Throwable {
  62.191 +        Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
  62.192 +        assertEquals(st.invoke(null, false, true, 10, 20), 20L, "Take 2nd value");
  62.193 +    }
  62.194 +
  62.195 +    @Test public void bothLong() throws Throwable {
  62.196 +        Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
  62.197 +        assertEquals(st.invoke(null, true, true, 10, 20), 30L, "Take both values");
  62.198 +    }
  62.199 +    
  62.200 +    @Test public void recordError() throws Throwable {
  62.201 +        Method st = methodClass.getMethod("recordError", Object.class);
  62.202 +        assertEquals(st.invoke(methodClass.newInstance(), "Hello"), "Hello", "The same parameter returned");
  62.203 +    }
  62.204 +}
  62.205 \ No newline at end of file
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/JsClassLoaderTest.java	Tue Jan 07 08:21:57 2014 +0100
    63.3 @@ -0,0 +1,155 @@
    63.4 +/**
    63.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    63.6 + *
    63.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    63.8 + *
    63.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   63.10 + * Other names may be trademarks of their respective owners.
   63.11 + *
   63.12 + * The contents of this file are subject to the terms of either the GNU
   63.13 + * General Public License Version 2 only ("GPL") or the Common
   63.14 + * Development and Distribution License("CDDL") (collectively, the
   63.15 + * "License"). You may not use this file except in compliance with the
   63.16 + * License. You can obtain a copy of the License at
   63.17 + * http://www.netbeans.org/cddl-gplv2.html
   63.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   63.19 + * specific language governing permissions and limitations under the
   63.20 + * License.  When distributing the software, include this License Header
   63.21 + * Notice in each file and include the License file at
   63.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   63.23 + * particular file as subject to the "Classpath" exception as provided
   63.24 + * by Oracle in the GPL Version 2 section of the License file that
   63.25 + * accompanied this code. If applicable, add the following below the
   63.26 + * License Header, with the fields enclosed by brackets [] replaced by
   63.27 + * your own identifying information:
   63.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   63.29 + *
   63.30 + * Contributor(s):
   63.31 + *
   63.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   63.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   63.34 + *
   63.35 + * If you wish your version of this file to be governed by only the CDDL
   63.36 + * or only the GPL Version 2, indicate your decision by adding
   63.37 + * "[Contributor] elects to include this software in this distribution
   63.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   63.39 + * single choice of license, a recipient has the option to distribute
   63.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   63.41 + * to extend the choice of license to its licensees as provided above.
   63.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   63.43 + * Version 2 license, then the option applies only if the new code is
   63.44 + * made subject to such option by the copyright holder.
   63.45 + */
   63.46 +package org.netbeans.html.boot.impl;
   63.47 +
   63.48 +import java.io.Closeable;
   63.49 +import java.io.Reader;
   63.50 +import org.apidesign.html.boot.spi.Fn;
   63.51 +import java.net.URL;
   63.52 +import java.net.URLClassLoader;
   63.53 +import java.util.ArrayList;
   63.54 +import java.util.Arrays;
   63.55 +import java.util.Enumeration;
   63.56 +import java.util.List;
   63.57 +import javax.script.Invocable;
   63.58 +import javax.script.ScriptEngine;
   63.59 +import javax.script.ScriptEngineManager;
   63.60 +import javax.script.ScriptException;
   63.61 +import org.testng.annotations.AfterClass;
   63.62 +import org.testng.annotations.BeforeClass;
   63.63 +import org.testng.annotations.BeforeMethod;
   63.64 +
   63.65 +/**
   63.66 + *
   63.67 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   63.68 + */
   63.69 +public class JsClassLoaderTest extends JsClassLoaderBase{
   63.70 +    private static Fn.Presenter loader;
   63.71 +
   63.72 +    @BeforeClass
   63.73 +    public static void setUpClass() throws Exception {
   63.74 +        ScriptEngineManager sem = new ScriptEngineManager();
   63.75 +        final ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
   63.76 +        
   63.77 +        final URL my = JsClassLoaderTest.class.getProtectionDomain().getCodeSource().getLocation();
   63.78 +        ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
   63.79 +        final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
   63.80 +        class MyCL extends JsClassLoader implements Fn.Presenter {
   63.81 +
   63.82 +            public MyCL(ClassLoader parent) {
   63.83 +                super(parent);
   63.84 +            }
   63.85 +            
   63.86 +            @Override
   63.87 +            protected URL findResource(String name) {
   63.88 +                return ul.getResource(name);
   63.89 +            }
   63.90 +            @Override
   63.91 +            public Fn defineFn(String code, String... names) {
   63.92 +                StringBuilder sb = new StringBuilder();
   63.93 +                sb.append("(function() {");
   63.94 +                sb.append("return function(");
   63.95 +                String sep = "";
   63.96 +                for (String n : names) {
   63.97 +                    sb.append(sep);
   63.98 +                    sb.append(n);
   63.99 +                    sep = ", ";
  63.100 +                }
  63.101 +                sb.append(") {");
  63.102 +                sb.append(code);
  63.103 +                sb.append("};");
  63.104 +                sb.append("})()");
  63.105 +                try {
  63.106 +                    final Object val = eng.eval(sb.toString());
  63.107 +                    return new Fn(this) {
  63.108 +                        @Override
  63.109 +                        public Object invoke(Object thiz, Object... args) throws Exception {
  63.110 +                            List<Object> all = new ArrayList<Object>(args.length + 1);
  63.111 +                            all.add(thiz == null ? val : thiz);
  63.112 +                            all.addAll(Arrays.asList(args));
  63.113 +                            Invocable inv = (Invocable)eng;
  63.114 +                            try {
  63.115 +                                Object ret = inv.invokeMethod(val, "call", all.toArray());
  63.116 +                                return val.equals(ret) ? null : ret;
  63.117 +                            } catch (Exception ex) {
  63.118 +                                throw ex;
  63.119 +                            }
  63.120 +                        }
  63.121 +                    };
  63.122 +                } catch (ScriptException ex) {
  63.123 +                    throw new LinkageError("Can't parse: " + sb, ex);
  63.124 +                }
  63.125 +            }
  63.126 +
  63.127 +            @Override
  63.128 +            protected Enumeration<URL> findResources(String name) {
  63.129 +                throw new UnsupportedOperationException();
  63.130 +            }
  63.131 +
  63.132 +            @Override
  63.133 +            public void loadScript(Reader code) throws ScriptException {
  63.134 +                eng.eval(code);
  63.135 +            }
  63.136 +
  63.137 +            @Override
  63.138 +            public void displayPage(URL page, Runnable onPageLoad) {
  63.139 +                throw new UnsupportedOperationException();
  63.140 +            }
  63.141 +        };
  63.142 +        
  63.143 +        MyCL l = new MyCL(parent);
  63.144 +        Closeable close = FnContext.activate(l);
  63.145 +        methodClass = l.loadClass(JsMethods.class.getName());
  63.146 +        close.close();
  63.147 +        loader = l;
  63.148 +    }
  63.149 +    
  63.150 +    @BeforeMethod public void initPresenter() {
  63.151 +        FnContext.currentPresenter(loader);
  63.152 +    }
  63.153 +
  63.154 +    @AfterClass
  63.155 +    public static void cleanUp() {
  63.156 +        methodClass = null;
  63.157 +    }
  63.158 +}
  63.159 \ No newline at end of file
    64.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/JsMethods.java	Tue Jan 07 08:21:57 2014 +0100
    64.3 @@ -0,0 +1,129 @@
    64.4 +/**
    64.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    64.6 + *
    64.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    64.8 + *
    64.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   64.10 + * Other names may be trademarks of their respective owners.
   64.11 + *
   64.12 + * The contents of this file are subject to the terms of either the GNU
   64.13 + * General Public License Version 2 only ("GPL") or the Common
   64.14 + * Development and Distribution License("CDDL") (collectively, the
   64.15 + * "License"). You may not use this file except in compliance with the
   64.16 + * License. You can obtain a copy of the License at
   64.17 + * http://www.netbeans.org/cddl-gplv2.html
   64.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   64.19 + * specific language governing permissions and limitations under the
   64.20 + * License.  When distributing the software, include this License Header
   64.21 + * Notice in each file and include the License file at
   64.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   64.23 + * particular file as subject to the "Classpath" exception as provided
   64.24 + * by Oracle in the GPL Version 2 section of the License file that
   64.25 + * accompanied this code. If applicable, add the following below the
   64.26 + * License Header, with the fields enclosed by brackets [] replaced by
   64.27 + * your own identifying information:
   64.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   64.29 + *
   64.30 + * Contributor(s):
   64.31 + *
   64.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   64.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   64.34 + *
   64.35 + * If you wish your version of this file to be governed by only the CDDL
   64.36 + * or only the GPL Version 2, indicate your decision by adding
   64.37 + * "[Contributor] elects to include this software in this distribution
   64.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   64.39 + * single choice of license, a recipient has the option to distribute
   64.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   64.41 + * to extend the choice of license to its licensees as provided above.
   64.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   64.43 + * Version 2 license, then the option applies only if the new code is
   64.44 + * made subject to such option by the copyright holder.
   64.45 + */
   64.46 +package org.netbeans.html.boot.impl;
   64.47 +
   64.48 +import net.java.html.js.JavaScriptBody;
   64.49 +import net.java.html.js.JavaScriptResource;
   64.50 +
   64.51 +
   64.52 +/**
   64.53 + *
   64.54 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   64.55 + */
   64.56 +@JavaScriptResource("jsmethods.js")
   64.57 +public class JsMethods {
   64.58 +    private Object value;
   64.59 +    
   64.60 +    @JavaScriptBody(args = {}, body = "return 42;")
   64.61 +    public static Object fortyTwo() {
   64.62 +        return -42;
   64.63 +    }
   64.64 +    
   64.65 +    @JavaScriptBody(args = {"x", "y" }, body = "return x + y;")
   64.66 +    public static native int plus(int x, int y);
   64.67 +    
   64.68 +    @JavaScriptBody(args = {"x"}, body = "return x;")
   64.69 +    public static native int plus(int x);
   64.70 +    
   64.71 +    @JavaScriptBody(args = {}, body = "return this;")
   64.72 +    public static native Object staticThis();
   64.73 +    
   64.74 +    @JavaScriptBody(args = {}, body = "return this;")
   64.75 +    public native Object getThis();
   64.76 +    @JavaScriptBody(args = {"x"}, body = "return x;")
   64.77 +    public native int plusInst(int x);
   64.78 +    
   64.79 +    @JavaScriptBody(args = {}, body = "return true;")
   64.80 +    public static boolean truth() {
   64.81 +        return false;
   64.82 +    }
   64.83 +    
   64.84 +    @JavaScriptBody(args = { "r" }, javacall=true, body = "r.@java.lang.Runnable::run()();")
   64.85 +    public static native void callback(Runnable r);
   64.86 +    
   64.87 +    @JavaScriptBody(args = { "at", "arr" }, javacall = true, body =
   64.88 +          "var a = 0;\n"
   64.89 +        + "for (var i = 0; i < arr.length; i++) {\n"
   64.90 +        + "  a = at.@org.netbeans.html.boot.impl.Arithm::sumTwo(II)(a, arr[i]);\n"
   64.91 +        + "}\n"
   64.92 +        + "return a;"
   64.93 +    )
   64.94 +    private static native int sumArr(Arithm at, int... arr);
   64.95 +    
   64.96 +    public static int sumArr(int... arr) {
   64.97 +        return sumArr(new Arithm(), arr);
   64.98 +    }
   64.99 +    
  64.100 +    @JavaScriptBody(args = { "x", "y" }, body = "return mul(x, y);")
  64.101 +    public static native int useExternalMul(int x, int y);
  64.102 +    
  64.103 +    @JavaScriptBody(args = { "m" }, javacall = true, body = "return m.@org.netbeans.html.boot.impl.JsMethods::getThis()();")
  64.104 +    public static native JsMethods returnYourSelf(JsMethods m);
  64.105 +    
  64.106 +    @JavaScriptBody(args = { "x", "y" }, javacall = true, body = "return @org.netbeans.html.boot.impl.JsMethods::useExternalMul(II)(x, y);")
  64.107 +    public static native int staticCallback(int x, int y);
  64.108 +
  64.109 +    @JavaScriptBody(args = { "v" }, javacall = true, body = "return @java.lang.Integer::parseInt(Ljava/lang/String;)(v);")
  64.110 +    public static native int parseInt(String v);
  64.111 +    
  64.112 +    @JavaScriptBody(args = { "useA", "useB", "a", "b" }, body = "var l = 0;"
  64.113 +        + "if (useA) l += a;\n"
  64.114 +        + "if (useB) l += b;\n"
  64.115 +        + "return l;\n"
  64.116 +    )
  64.117 +    public static native long chooseLong(boolean useA, boolean useB, long a, long b);
  64.118 +    
  64.119 +    protected void onError(Object o) throws Exception {
  64.120 +        value = o;
  64.121 +    }
  64.122 +    
  64.123 +    Object getError() {
  64.124 +        return value;
  64.125 +    }
  64.126 +    
  64.127 +    @JavaScriptBody(args = { "err" }, javacall = true, body = 
  64.128 +        "this.@org.netbeans.html.boot.impl.JsMethods::onError(Ljava/lang/Object;)(err);"
  64.129 +      + "return this.@org.netbeans.html.boot.impl.JsMethods::getError()();"
  64.130 +    )
  64.131 +    public native Object recordError(Object err);
  64.132 +}
    65.1 --- a/boot/src/test/resources/org/apidesign/html/boot/impl/jsmethods.js	Thu Dec 19 17:11:01 2013 +0100
    65.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.3 @@ -1,22 +0,0 @@
    65.4 -/*
    65.5 - * HTML via Java(tm) Language Bindings
    65.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    65.7 - *
    65.8 - * This program is free software: you can redistribute it and/or modify
    65.9 - * it under the terms of the GNU General Public License as published by
   65.10 - * the Free Software Foundation, version 2 of the License.
   65.11 - *
   65.12 - * This program is distributed in the hope that it will be useful,
   65.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   65.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   65.15 - * GNU General Public License for more details. apidesign.org
   65.16 - * designates this particular file as subject to the
   65.17 - * "Classpath" exception as provided by apidesign.org
   65.18 - * in the License file that accompanied this code.
   65.19 - *
   65.20 - * You should have received a copy of the GNU General Public License
   65.21 - * along with this program. Look for COPYING file in the top folder.
   65.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   65.23 - */
   65.24 -
   65.25 -function mul(x, y) { return x * y; }
    66.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.2 +++ b/boot/src/test/resources/org/netbeans/html/boot/impl/jsmethods.js	Tue Jan 07 08:21:57 2014 +0100
    66.3 @@ -0,0 +1,43 @@
    66.4 +/*
    66.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    66.6 + *
    66.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    66.8 + *
    66.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   66.10 + * Other names may be trademarks of their respective owners.
   66.11 + *
   66.12 + * The contents of this file are subject to the terms of either the GNU
   66.13 + * General Public License Version 2 only ("GPL") or the Common
   66.14 + * Development and Distribution License("CDDL") (collectively, the
   66.15 + * "License"). You may not use this file except in compliance with the
   66.16 + * License. You can obtain a copy of the License at
   66.17 + * http://www.netbeans.org/cddl-gplv2.html
   66.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   66.19 + * specific language governing permissions and limitations under the
   66.20 + * License.  When distributing the software, include this License Header
   66.21 + * Notice in each file and include the License file at
   66.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   66.23 + * particular file as subject to the "Classpath" exception as provided
   66.24 + * by Oracle in the GPL Version 2 section of the License file that
   66.25 + * accompanied this code. If applicable, add the following below the
   66.26 + * License Header, with the fields enclosed by brackets [] replaced by
   66.27 + * your own identifying information:
   66.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   66.29 + *
   66.30 + * Contributor(s):
   66.31 + *
   66.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   66.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   66.34 + *
   66.35 + * If you wish your version of this file to be governed by only the CDDL
   66.36 + * or only the GPL Version 2, indicate your decision by adding
   66.37 + * "[Contributor] elects to include this software in this distribution
   66.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   66.39 + * single choice of license, a recipient has the option to distribute
   66.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   66.41 + * to extend the choice of license to its licensees as provided above.
   66.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   66.43 + * Version 2 license, then the option applies only if the new code is
   66.44 + * made subject to such option by the copyright holder.
   66.45 + */
   66.46 +function mul(x, y) { return x * y; }
    67.1 --- a/context/pom.xml	Thu Dec 19 17:11:01 2013 +0100
    67.2 +++ b/context/pom.xml	Tue Jan 07 08:21:57 2014 +0100
    67.3 @@ -2,11 +2,11 @@
    67.4  <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">
    67.5    <modelVersion>4.0.0</modelVersion>
    67.6    <parent>
    67.7 -    <groupId>org.apidesign</groupId>
    67.8 -    <artifactId>html</artifactId>
    67.9 +    <groupId>org.netbeans.html</groupId>
   67.10 +    <artifactId>pom</artifactId>
   67.11      <version>0.7-SNAPSHOT</version>
   67.12    </parent>
   67.13 -  <groupId>org.apidesign.html</groupId>
   67.14 +  <groupId>org.netbeans.html</groupId>
   67.15    <artifactId>net.java.html</artifactId>
   67.16    <version>0.7-SNAPSHOT</version>
   67.17    <packaging>bundle</packaging>
    68.1 --- a/context/src/main/java/net/java/html/BrwsrCtx.java	Thu Dec 19 17:11:01 2013 +0100
    68.2 +++ b/context/src/main/java/net/java/html/BrwsrCtx.java	Tue Jan 07 08:21:57 2014 +0100
    68.3 @@ -1,29 +1,51 @@
    68.4  /**
    68.5 - * HTML via Java(tm) Language Bindings
    68.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    68.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    68.8   *
    68.9 - * This program is free software: you can redistribute it and/or modify
   68.10 - * it under the terms of the GNU General Public License as published by
   68.11 - * the Free Software Foundation, version 2 of the License.
   68.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   68.13   *
   68.14 - * This program is distributed in the hope that it will be useful,
   68.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   68.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   68.17 - * GNU General Public License for more details. apidesign.org
   68.18 - * designates this particular file as subject to the
   68.19 - * "Classpath" exception as provided by apidesign.org
   68.20 - * in the License file that accompanied this code.
   68.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   68.22 + * Other names may be trademarks of their respective owners.
   68.23   *
   68.24 - * You should have received a copy of the GNU General Public License
   68.25 - * along with this program. Look for COPYING file in the top folder.
   68.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   68.27 + * The contents of this file are subject to the terms of either the GNU
   68.28 + * General Public License Version 2 only ("GPL") or the Common
   68.29 + * Development and Distribution License("CDDL") (collectively, the
   68.30 + * "License"). You may not use this file except in compliance with the
   68.31 + * License. You can obtain a copy of the License at
   68.32 + * http://www.netbeans.org/cddl-gplv2.html
   68.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   68.34 + * specific language governing permissions and limitations under the
   68.35 + * License.  When distributing the software, include this License Header
   68.36 + * Notice in each file and include the License file at
   68.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   68.38 + * particular file as subject to the "Classpath" exception as provided
   68.39 + * by Oracle in the GPL Version 2 section of the License file that
   68.40 + * accompanied this code. If applicable, add the following below the
   68.41 + * License Header, with the fields enclosed by brackets [] replaced by
   68.42 + * your own identifying information:
   68.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   68.44 + *
   68.45 + * Contributor(s):
   68.46 + *
   68.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   68.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   68.49 + *
   68.50 + * If you wish your version of this file to be governed by only the CDDL
   68.51 + * or only the GPL Version 2, indicate your decision by adding
   68.52 + * "[Contributor] elects to include this software in this distribution
   68.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   68.54 + * single choice of license, a recipient has the option to distribute
   68.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   68.56 + * to extend the choice of license to its licensees as provided above.
   68.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   68.58 + * Version 2 license, then the option applies only if the new code is
   68.59 + * made subject to such option by the copyright holder.
   68.60   */
   68.61  package net.java.html;
   68.62  
   68.63  import java.util.ServiceLoader;
   68.64  import java.util.logging.Logger;
   68.65 -import org.apidesign.html.context.impl.CtxAccssr;
   68.66 -import org.apidesign.html.context.impl.CtxImpl;
   68.67 +import org.netbeans.html.context.impl.CtxAccssr;
   68.68 +import org.netbeans.html.context.impl.CtxImpl;
   68.69  import org.apidesign.html.context.spi.Contexts;
   68.70  
   68.71  /** Represents context where the <code>net.java.html.json.Model</code>
    69.1 --- a/context/src/main/java/org/apidesign/html/context/impl/CtxAccssr.java	Thu Dec 19 17:11:01 2013 +0100
    69.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.3 @@ -1,52 +0,0 @@
    69.4 -/**
    69.5 - * HTML via Java(tm) Language Bindings
    69.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    69.7 - *
    69.8 - * This program is free software: you can redistribute it and/or modify
    69.9 - * it under the terms of the GNU General Public License as published by
   69.10 - * the Free Software Foundation, version 2 of the License.
   69.11 - *
   69.12 - * This program is distributed in the hope that it will be useful,
   69.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   69.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   69.15 - * GNU General Public License for more details. apidesign.org
   69.16 - * designates this particular file as subject to the
   69.17 - * "Classpath" exception as provided by apidesign.org
   69.18 - * in the License file that accompanied this code.
   69.19 - *
   69.20 - * You should have received a copy of the GNU General Public License
   69.21 - * along with this program. Look for COPYING file in the top folder.
   69.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   69.23 - */
   69.24 -package org.apidesign.html.context.impl;
   69.25 -
   69.26 -import net.java.html.BrwsrCtx;
   69.27 -
   69.28 -/** Internal communication between API (e.g. {@link BrwsrCtx}), SPI
   69.29 - * (e.g. {@link ContextBuilder}) and the implementation package.
   69.30 - *
   69.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   69.32 - */
   69.33 -public abstract class CtxAccssr {
   69.34 -    private static CtxAccssr DEFAULT;
   69.35 -    static {
   69.36 -        // run initializers
   69.37 -        try {
   69.38 -            BrwsrCtx.EMPTY.getClass();
   69.39 -        } catch (NullPointerException ex) {
   69.40 -            // ignore
   69.41 -        }
   69.42 -    }
   69.43 -    
   69.44 -    protected CtxAccssr() {
   69.45 -        if (DEFAULT != null) throw new IllegalStateException();
   69.46 -        DEFAULT = this;
   69.47 -    }
   69.48 -    
   69.49 -    protected abstract BrwsrCtx newContext(CtxImpl impl);
   69.50 -    protected abstract CtxImpl find(BrwsrCtx context);
   69.51 -    
   69.52 -    static CtxAccssr getDefault() {
   69.53 -        return DEFAULT;
   69.54 -    }
   69.55 -}
    70.1 --- a/context/src/main/java/org/apidesign/html/context/impl/CtxImpl.java	Thu Dec 19 17:11:01 2013 +0100
    70.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.3 @@ -1,88 +0,0 @@
    70.4 -/**
    70.5 - * HTML via Java(tm) Language Bindings
    70.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    70.7 - *
    70.8 - * This program is free software: you can redistribute it and/or modify
    70.9 - * it under the terms of the GNU General Public License as published by
   70.10 - * the Free Software Foundation, version 2 of the License.
   70.11 - *
   70.12 - * This program is distributed in the hope that it will be useful,
   70.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   70.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   70.15 - * GNU General Public License for more details. apidesign.org
   70.16 - * designates this particular file as subject to the
   70.17 - * "Classpath" exception as provided by apidesign.org
   70.18 - * in the License file that accompanied this code.
   70.19 - *
   70.20 - * You should have received a copy of the GNU General Public License
   70.21 - * along with this program. Look for COPYING file in the top folder.
   70.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   70.23 - */
   70.24 -package org.apidesign.html.context.impl;
   70.25 -
   70.26 -import java.util.ArrayList;
   70.27 -import java.util.Collections;
   70.28 -import java.util.List;
   70.29 -import net.java.html.BrwsrCtx;
   70.30 -
   70.31 -/** Implementation detail. Holds list of technologies for particular
   70.32 - * {@link BrwsrCtx}.
   70.33 - *
   70.34 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   70.35 - */
   70.36 -public final class CtxImpl {
   70.37 -    private final List<Bind<?>> techs;
   70.38 -    
   70.39 -    public CtxImpl() {
   70.40 -        techs = new ArrayList<Bind<?>>();
   70.41 -    }
   70.42 -    
   70.43 -    private CtxImpl(List<Bind<?>> techs) {
   70.44 -        this.techs = techs;
   70.45 -    }
   70.46 -    
   70.47 -    public static <Tech> Tech find(BrwsrCtx context, Class<Tech> technology) {
   70.48 -        CtxImpl impl = CtxAccssr.getDefault().find(context);
   70.49 -        for (Bind<?> bind : impl.techs) {
   70.50 -            if (technology == bind.clazz) {
   70.51 -                return technology.cast(bind.impl);
   70.52 -            }
   70.53 -        }
   70.54 -        return null;
   70.55 -    }
   70.56 -
   70.57 -    public BrwsrCtx build() {
   70.58 -        Collections.sort(techs);
   70.59 -        CtxImpl impl = new CtxImpl(Collections.unmodifiableList(techs));
   70.60 -        return CtxAccssr.getDefault().newContext(impl);
   70.61 -    }
   70.62 -
   70.63 -    public <Tech> void register(Class<Tech> type, Tech impl, int priority) {
   70.64 -        techs.add(new Bind<Tech>(type, impl, priority));
   70.65 -    }
   70.66 -    
   70.67 -    private static final class Bind<Tech> implements Comparable<Bind<?>> {
   70.68 -        private final Class<Tech> clazz;
   70.69 -        private final Tech impl;
   70.70 -        private final int priority;
   70.71 -
   70.72 -        public Bind(Class<Tech> clazz, Tech impl, int priority) {
   70.73 -            this.clazz = clazz;
   70.74 -            this.impl = impl;
   70.75 -            this.priority = priority;
   70.76 -        }
   70.77 -
   70.78 -        @Override
   70.79 -        public int compareTo(Bind<?> o) {
   70.80 -            if (priority != o.priority) {
   70.81 -                return priority - o.priority;
   70.82 -            }
   70.83 -            return clazz.getName().compareTo(o.clazz.getName());
   70.84 -        }
   70.85 -
   70.86 -        @Override
   70.87 -        public String toString() {
   70.88 -            return "Bind{" + "clazz=" + clazz + "@" + clazz.getClassLoader() + ", impl=" + impl + ", priority=" + priority + '}';
   70.89 -        }
   70.90 -    }
   70.91 -}
    71.1 --- a/context/src/main/java/org/apidesign/html/context/spi/Contexts.java	Thu Dec 19 17:11:01 2013 +0100
    71.2 +++ b/context/src/main/java/org/apidesign/html/context/spi/Contexts.java	Tue Jan 07 08:21:57 2014 +0100
    71.3 @@ -1,27 +1,49 @@
    71.4  /**
    71.5 - * HTML via Java(tm) Language Bindings
    71.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    71.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    71.8   *
    71.9 - * This program is free software: you can redistribute it and/or modify
   71.10 - * it under the terms of the GNU General Public License as published by
   71.11 - * the Free Software Foundation, version 2 of the License.
   71.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   71.13   *
   71.14 - * This program is distributed in the hope that it will be useful,
   71.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   71.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   71.17 - * GNU General Public License for more details. apidesign.org
   71.18 - * designates this particular file as subject to the
   71.19 - * "Classpath" exception as provided by apidesign.org
   71.20 - * in the License file that accompanied this code.
   71.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   71.22 + * Other names may be trademarks of their respective owners.
   71.23   *
   71.24 - * You should have received a copy of the GNU General Public License
   71.25 - * along with this program. Look for COPYING file in the top folder.
   71.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   71.27 + * The contents of this file are subject to the terms of either the GNU
   71.28 + * General Public License Version 2 only ("GPL") or the Common
   71.29 + * Development and Distribution License("CDDL") (collectively, the
   71.30 + * "License"). You may not use this file except in compliance with the
   71.31 + * License. You can obtain a copy of the License at
   71.32 + * http://www.netbeans.org/cddl-gplv2.html
   71.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   71.34 + * specific language governing permissions and limitations under the
   71.35 + * License.  When distributing the software, include this License Header
   71.36 + * Notice in each file and include the License file at
   71.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   71.38 + * particular file as subject to the "Classpath" exception as provided
   71.39 + * by Oracle in the GPL Version 2 section of the License file that
   71.40 + * accompanied this code. If applicable, add the following below the
   71.41 + * License Header, with the fields enclosed by brackets [] replaced by
   71.42 + * your own identifying information:
   71.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   71.44 + *
   71.45 + * Contributor(s):
   71.46 + *
   71.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   71.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   71.49 + *
   71.50 + * If you wish your version of this file to be governed by only the CDDL
   71.51 + * or only the GPL Version 2, indicate your decision by adding
   71.52 + * "[Contributor] elects to include this software in this distribution
   71.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   71.54 + * single choice of license, a recipient has the option to distribute
   71.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   71.56 + * to extend the choice of license to its licensees as provided above.
   71.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   71.58 + * Version 2 license, then the option applies only if the new code is
   71.59 + * made subject to such option by the copyright holder.
   71.60   */
   71.61  package org.apidesign.html.context.spi;
   71.62  
   71.63  import net.java.html.BrwsrCtx;
   71.64 -import org.apidesign.html.context.impl.CtxImpl;
   71.65 +import org.netbeans.html.context.impl.CtxImpl;
   71.66  
   71.67  /**
   71.68   *
    72.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.2 +++ b/context/src/main/java/org/netbeans/html/context/impl/CtxAccssr.java	Tue Jan 07 08:21:57 2014 +0100
    72.3 @@ -0,0 +1,74 @@
    72.4 +/**
    72.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    72.6 + *
    72.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    72.8 + *
    72.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   72.10 + * Other names may be trademarks of their respective owners.
   72.11 + *
   72.12 + * The contents of this file are subject to the terms of either the GNU
   72.13 + * General Public License Version 2 only ("GPL") or the Common
   72.14 + * Development and Distribution License("CDDL") (collectively, the
   72.15 + * "License"). You may not use this file except in compliance with the
   72.16 + * License. You can obtain a copy of the License at
   72.17 + * http://www.netbeans.org/cddl-gplv2.html
   72.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   72.19 + * specific language governing permissions and limitations under the
   72.20 + * License.  When distributing the software, include this License Header
   72.21 + * Notice in each file and include the License file at
   72.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   72.23 + * particular file as subject to the "Classpath" exception as provided
   72.24 + * by Oracle in the GPL Version 2 section of the License file that
   72.25 + * accompanied this code. If applicable, add the following below the
   72.26 + * License Header, with the fields enclosed by brackets [] replaced by
   72.27 + * your own identifying information:
   72.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   72.29 + *
   72.30 + * Contributor(s):
   72.31 + *
   72.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   72.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   72.34 + *
   72.35 + * If you wish your version of this file to be governed by only the CDDL
   72.36 + * or only the GPL Version 2, indicate your decision by adding
   72.37 + * "[Contributor] elects to include this software in this distribution
   72.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   72.39 + * single choice of license, a recipient has the option to distribute
   72.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   72.41 + * to extend the choice of license to its licensees as provided above.
   72.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   72.43 + * Version 2 license, then the option applies only if the new code is
   72.44 + * made subject to such option by the copyright holder.
   72.45 + */
   72.46 +package org.netbeans.html.context.impl;
   72.47 +
   72.48 +import net.java.html.BrwsrCtx;
   72.49 +
   72.50 +/** Internal communication between API (e.g. {@link BrwsrCtx}), SPI
   72.51 + * (e.g. {@link ContextBuilder}) and the implementation package.
   72.52 + *
   72.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   72.54 + */
   72.55 +public abstract class CtxAccssr {
   72.56 +    private static CtxAccssr DEFAULT;
   72.57 +    static {
   72.58 +        // run initializers
   72.59 +        try {
   72.60 +            BrwsrCtx.EMPTY.getClass();
   72.61 +        } catch (NullPointerException ex) {
   72.62 +            // ignore
   72.63 +        }
   72.64 +    }
   72.65 +    
   72.66 +    protected CtxAccssr() {
   72.67 +        if (DEFAULT != null) throw new IllegalStateException();
   72.68 +        DEFAULT = this;
   72.69 +    }
   72.70 +    
   72.71 +    protected abstract BrwsrCtx newContext(CtxImpl impl);
   72.72 +    protected abstract CtxImpl find(BrwsrCtx context);
   72.73 +    
   72.74 +    static CtxAccssr getDefault() {
   72.75 +        return DEFAULT;
   72.76 +    }
   72.77 +}
    73.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    73.2 +++ b/context/src/main/java/org/netbeans/html/context/impl/CtxImpl.java	Tue Jan 07 08:21:57 2014 +0100
    73.3 @@ -0,0 +1,110 @@
    73.4 +/**
    73.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    73.6 + *
    73.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    73.8 + *
    73.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   73.10 + * Other names may be trademarks of their respective owners.
   73.11 + *
   73.12 + * The contents of this file are subject to the terms of either the GNU
   73.13 + * General Public License Version 2 only ("GPL") or the Common
   73.14 + * Development and Distribution License("CDDL") (collectively, the
   73.15 + * "License"). You may not use this file except in compliance with the
   73.16 + * License. You can obtain a copy of the License at
   73.17 + * http://www.netbeans.org/cddl-gplv2.html
   73.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   73.19 + * specific language governing permissions and limitations under the
   73.20 + * License.  When distributing the software, include this License Header
   73.21 + * Notice in each file and include the License file at
   73.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   73.23 + * particular file as subject to the "Classpath" exception as provided
   73.24 + * by Oracle in the GPL Version 2 section of the License file that
   73.25 + * accompanied this code. If applicable, add the following below the
   73.26 + * License Header, with the fields enclosed by brackets [] replaced by
   73.27 + * your own identifying information:
   73.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   73.29 + *
   73.30 + * Contributor(s):
   73.31 + *
   73.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   73.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   73.34 + *
   73.35 + * If you wish your version of this file to be governed by only the CDDL
   73.36 + * or only the GPL Version 2, indicate your decision by adding
   73.37 + * "[Contributor] elects to include this software in this distribution
   73.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   73.39 + * single choice of license, a recipient has the option to distribute
   73.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   73.41 + * to extend the choice of license to its licensees as provided above.
   73.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   73.43 + * Version 2 license, then the option applies only if the new code is
   73.44 + * made subject to such option by the copyright holder.
   73.45 + */
   73.46 +package org.netbeans.html.context.impl;
   73.47 +
   73.48 +import java.util.ArrayList;
   73.49 +import java.util.Collections;
   73.50 +import java.util.List;
   73.51 +import net.java.html.BrwsrCtx;
   73.52 +
   73.53 +/** Implementation detail. Holds list of technologies for particular
   73.54 + * {@link BrwsrCtx}.
   73.55 + *
   73.56 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   73.57 + */
   73.58 +public final class CtxImpl {
   73.59 +    private final List<Bind<?>> techs;
   73.60 +    
   73.61 +    public CtxImpl() {
   73.62 +        techs = new ArrayList<Bind<?>>();
   73.63 +    }
   73.64 +    
   73.65 +    private CtxImpl(List<Bind<?>> techs) {
   73.66 +        this.techs = techs;
   73.67 +    }
   73.68 +    
   73.69 +    public static <Tech> Tech find(BrwsrCtx context, Class<Tech> technology) {
   73.70 +        CtxImpl impl = CtxAccssr.getDefault().find(context);
   73.71 +        for (Bind<?> bind : impl.techs) {
   73.72 +            if (technology == bind.clazz) {
   73.73 +                return technology.cast(bind.impl);
   73.74 +            }
   73.75 +        }
   73.76 +        return null;
   73.77 +    }
   73.78 +
   73.79 +    public BrwsrCtx build() {
   73.80 +        Collections.sort(techs);
   73.81 +        CtxImpl impl = new CtxImpl(Collections.unmodifiableList(techs));
   73.82 +        return CtxAccssr.getDefault().newContext(impl);
   73.83 +    }
   73.84 +
   73.85 +    public <Tech> void register(Class<Tech> type, Tech impl, int priority) {
   73.86 +        techs.add(new Bind<Tech>(type, impl, priority));
   73.87 +    }
   73.88 +    
   73.89 +    private static final class Bind<Tech> implements Comparable<Bind<?>> {
   73.90 +        private final Class<Tech> clazz;
   73.91 +        private final Tech impl;
   73.92 +        private final int priority;
   73.93 +
   73.94 +        public Bind(Class<Tech> clazz, Tech impl, int priority) {
   73.95 +            this.clazz = clazz;
   73.96 +            this.impl = impl;
   73.97 +            this.priority = priority;
   73.98 +        }
   73.99 +
  73.100 +        @Override
  73.101 +        public int compareTo(Bind<?> o) {
  73.102 +            if (priority != o.priority) {
  73.103 +                return priority - o.priority;
  73.104 +            }
  73.105 +            return clazz.getName().compareTo(o.clazz.getName());
  73.106 +        }
  73.107 +
  73.108 +        @Override
  73.109 +        public String toString() {
  73.110 +            return "Bind{" + "clazz=" + clazz + "@" + clazz.getClassLoader() + ", impl=" + impl + ", priority=" + priority + '}';
  73.111 +        }
  73.112 +    }
  73.113 +}
    74.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    74.2 +++ b/equinox-agentclass-hook/pom.xml	Tue Jan 07 08:21:57 2014 +0100
    74.3 @@ -0,0 +1,42 @@
    74.4 +<?xml version="1.0" encoding="UTF-8"?>
    74.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">
    74.6 +    <modelVersion>4.0.0</modelVersion>
    74.7 +    <parent>
    74.8 +        <groupId>org.netbeans.html</groupId>
    74.9 +        <artifactId>pom</artifactId>
   74.10 +        <version>0.7-SNAPSHOT</version>
   74.11 +    </parent>
   74.12 +    <name>AgentClass Hook for Equinox</name>
   74.13 +    <artifactId>equinox-agentclass-hook</artifactId>
   74.14 +    <packaging>bundle</packaging>
   74.15 +    <build>
   74.16 +        <plugins>
   74.17 +            <plugin>
   74.18 +                <groupId>org.apache.felix</groupId>
   74.19 +                <artifactId>maven-bundle-plugin</artifactId>
   74.20 +                <configuration>
   74.21 +                    <instructions>
   74.22 +                        <Fragment-Host>org.eclipse.osgi;bundle-version="[3.8.0,4.0)"</Fragment-Host>
   74.23 +                        <Import-Package></Import-Package>
   74.24 +                    </instructions>
   74.25 +                </configuration>
   74.26 +            </plugin>
   74.27 +            <plugin>
   74.28 +                <groupId>org.apache.maven.plugins</groupId>
   74.29 +                <artifactId>maven-compiler-plugin</artifactId>
   74.30 +                <version>2.3.2</version>
   74.31 +                <configuration>
   74.32 +                    <source>1.5</source>
   74.33 +                    <target>1.5</target>
   74.34 +                </configuration>
   74.35 +            </plugin>
   74.36 +        </plugins>
   74.37 +    </build>
   74.38 +    <dependencies>
   74.39 +        <dependency>
   74.40 +            <groupId>org.eclipse</groupId>
   74.41 +            <artifactId>org.eclipse.osgi</artifactId>
   74.42 +            <version>3.8.0.v20120529-1548</version>
   74.43 +        </dependency>
   74.44 +    </dependencies>
   74.45 +</project>
   74.46 \ No newline at end of file
    75.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    75.2 +++ b/equinox-agentclass-hook/src/main/java/org/netbeans/html/equinox/agentclass/AgentHook.java	Tue Jan 07 08:21:57 2014 +0100
    75.3 @@ -0,0 +1,164 @@
    75.4 +/**
    75.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    75.6 + *
    75.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    75.8 + *
    75.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   75.10 + * Other names may be trademarks of their respective owners.
   75.11 + *
   75.12 + * The contents of this file are subject to the terms of either the GNU
   75.13 + * General Public License Version 2 only ("GPL") or the Common
   75.14 + * Development and Distribution License("CDDL") (collectively, the
   75.15 + * "License"). You may not use this file except in compliance with the
   75.16 + * License. You can obtain a copy of the License at
   75.17 + * http://www.netbeans.org/cddl-gplv2.html
   75.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   75.19 + * specific language governing permissions and limitations under the
   75.20 + * License.  When distributing the software, include this License Header
   75.21 + * Notice in each file and include the License file at
   75.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   75.23 + * particular file as subject to the "Classpath" exception as provided
   75.24 + * by Oracle in the GPL Version 2 section of the License file that
   75.25 + * accompanied this code. If applicable, add the following below the
   75.26 + * License Header, with the fields enclosed by brackets [] replaced by
   75.27 + * your own identifying information:
   75.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   75.29 + *
   75.30 + * Contributor(s):
   75.31 + *
   75.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   75.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   75.34 + *
   75.35 + * If you wish your version of this file to be governed by only the CDDL
   75.36 + * or only the GPL Version 2, indicate your decision by adding
   75.37 + * "[Contributor] elects to include this software in this distribution
   75.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   75.39 + * single choice of license, a recipient has the option to distribute
   75.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   75.41 + * to extend the choice of license to its licensees as provided above.
   75.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   75.43 + * Version 2 license, then the option applies only if the new code is
   75.44 + * made subject to such option by the copyright holder.
   75.45 + */
   75.46 +package org.netbeans.html.equinox.agentclass;
   75.47 +
   75.48 +import java.lang.instrument.IllegalClassFormatException;
   75.49 +import java.security.ProtectionDomain;
   75.50 +import java.util.ArrayList;
   75.51 +import java.util.logging.Logger;
   75.52 +
   75.53 +import org.eclipse.osgi.baseadaptor.BaseData;
   75.54 +import org.eclipse.osgi.baseadaptor.HookConfigurator;
   75.55 +import org.eclipse.osgi.baseadaptor.HookRegistry;
   75.56 +import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
   75.57 +import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook;
   75.58 +import org.eclipse.osgi.baseadaptor.loader.BaseClassLoader;
   75.59 +import org.eclipse.osgi.baseadaptor.loader.ClasspathEntry;
   75.60 +import org.eclipse.osgi.baseadaptor.loader.ClasspathManager;
   75.61 +import org.eclipse.osgi.framework.adaptor.BundleProtectionDomain;
   75.62 +import org.eclipse.osgi.framework.adaptor.BundleWatcher;
   75.63 +import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate;
   75.64 +import org.osgi.framework.Bundle;
   75.65 +import org.osgi.framework.BundleContext;
   75.66 +import org.osgi.framework.wiring.BundleWiring;
   75.67 +
   75.68 +public class AgentHook implements HookConfigurator, BundleWatcher, ClassLoadingHook {
   75.69 +    private static final Logger LOG = Logger.getLogger(AgentHook.class.getName());
   75.70 +	private boolean all;
   75.71 +	
   75.72 +	@Override
   75.73 +	public void addHooks(HookRegistry hookRegistry) {
   75.74 +		LOG.info("Agent hook for Equinox initialized!");
   75.75 +		hookRegistry.addWatcher(this);
   75.76 +		hookRegistry.addClassLoadingHook(this);
   75.77 +	}
   75.78 +
   75.79 +	@Override
   75.80 +	public void watchBundle(Bundle bundle, int type) {
   75.81 +		if (!all) {
   75.82 +			BundleContext c = bundle.getBundleContext();
   75.83 +			if (c != null) {
   75.84 +				Bundle[] arr = bundle.getBundleContext().getBundles();
   75.85 +				for (Bundle b : arr) {
   75.86 +					agentBundle(b);
   75.87 +				}
   75.88 +				all = true;
   75.89 +			}
   75.90 +		}
   75.91 +		if (type == BundleWatcher.END_ACTIVATION) {
   75.92 +			agentBundle(bundle);
   75.93 +		}
   75.94 +	}
   75.95 +
   75.96 +	private void agentBundle(Bundle bundle) {
   75.97 +		String agentClass = (String)bundle.getHeaders().get("Agent-Class");
   75.98 +		if (agentClass != null) {
   75.99 +			Class<?> agent;
  75.100 +			try {
  75.101 +				agent = bundle.loadClass(agentClass);
  75.102 +				NbInstrumentation.registerAgent(agent.getClassLoader(), agent.getName());
  75.103 +			} catch (ClassNotFoundException e) {
  75.104 +				throw new IllegalStateException(e);
  75.105 +			}
  75.106 +		}
  75.107 +	}
  75.108 +
  75.109 +	@Override
  75.110 +	public byte[] processClass(String name, byte[] bytes,
  75.111 +			ClasspathEntry ce, BundleEntry entry,
  75.112 +			ClasspathManager manager) {
  75.113 +        final BaseData bd = ce.getBaseData();
  75.114 +        if (bd == null) {
  75.115 +            return bytes;
  75.116 +        }
  75.117 +        final Bundle b = bd.getBundle();
  75.118 +        if (b == null) {
  75.119 +            return bytes;
  75.120 +        }
  75.121 +        BundleWiring w = (BundleWiring)b.adapt(BundleWiring.class);
  75.122 +        if (w == null) {
  75.123 +            return bytes;
  75.124 +        }
  75.125 +        ClassLoader loader = w.getClassLoader();
  75.126 +		try {
  75.127 +			return NbInstrumentation.patchByteCode(loader, name, ce.getDomain(), bytes);
  75.128 +		} catch (IllegalClassFormatException e) {
  75.129 +			return bytes;
  75.130 +		}
  75.131 +	}
  75.132 +
  75.133 +	@Override
  75.134 +	public boolean addClassPathEntry(ArrayList cpEntries,
  75.135 +			String cp, ClasspathManager hostmanager, BaseData sourcedata,
  75.136 +			ProtectionDomain sourcedomain) {
  75.137 +		// TODO Auto-generated method stub
  75.138 +		return false;
  75.139 +	}
  75.140 +
  75.141 +	@Override
  75.142 +	public String findLibrary(BaseData data, String libName) {
  75.143 +		// TODO Auto-generated method stub
  75.144 +		return null;
  75.145 +	}
  75.146 +
  75.147 +	@Override
  75.148 +	public ClassLoader getBundleClassLoaderParent() {
  75.149 +		// TODO Auto-generated method stub
  75.150 +		return null;
  75.151 +	}
  75.152 +
  75.153 +	@Override
  75.154 +	public BaseClassLoader createClassLoader(ClassLoader parent,
  75.155 +			ClassLoaderDelegate delegate, BundleProtectionDomain domain,
  75.156 +			BaseData data, String[] bundleclasspath) {
  75.157 +		// TODO Auto-generated method stub
  75.158 +		return null;
  75.159 +	}
  75.160 +
  75.161 +	@Override
  75.162 +	public void initializedClassLoader(BaseClassLoader baseClassLoader,
  75.163 +			BaseData data) {
  75.164 +		// TODO Auto-generated method stub
  75.165 +		
  75.166 +	}
  75.167 +}
    76.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.2 +++ b/equinox-agentclass-hook/src/main/java/org/netbeans/html/equinox/agentclass/NbInstrumentation.java	Tue Jan 07 08:21:57 2014 +0100
    76.3 @@ -0,0 +1,214 @@
    76.4 +/**
    76.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    76.6 + *
    76.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    76.8 + *
    76.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   76.10 + * Other names may be trademarks of their respective owners.
   76.11 + *
   76.12 + * The contents of this file are subject to the terms of either the GNU
   76.13 + * General Public License Version 2 only ("GPL") or the Common
   76.14 + * Development and Distribution License("CDDL") (collectively, the
   76.15 + * "License"). You may not use this file except in compliance with the
   76.16 + * License. You can obtain a copy of the License at
   76.17 + * http://www.netbeans.org/cddl-gplv2.html
   76.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   76.19 + * specific language governing permissions and limitations under the
   76.20 + * License.  When distributing the software, include this License Header
   76.21 + * Notice in each file and include the License file at
   76.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   76.23 + * particular file as subject to the "Classpath" exception as provided
   76.24 + * by Oracle in the GPL Version 2 section of the License file that
   76.25 + * accompanied this code. If applicable, add the following below the
   76.26 + * License Header, with the fields enclosed by brackets [] replaced by
   76.27 + * your own identifying information:
   76.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   76.29 + *
   76.30 + * Contributor(s):
   76.31 + *
   76.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   76.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   76.34 + *
   76.35 + * If you wish your version of this file to be governed by only the CDDL
   76.36 + * or only the GPL Version 2, indicate your decision by adding
   76.37 + * "[Contributor] elects to include this software in this distribution
   76.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   76.39 + * single choice of license, a recipient has the option to distribute
   76.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   76.41 + * to extend the choice of license to its licensees as provided above.
   76.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   76.43 + * Version 2 license, then the option applies only if the new code is
   76.44 + * made subject to such option by the copyright holder.
   76.45 + */
   76.46 +
   76.47 +package org.netbeans.html.equinox.agentclass;
   76.48 +
   76.49 +import java.lang.instrument.ClassDefinition;
   76.50 +import java.lang.instrument.ClassFileTransformer;
   76.51 +import java.lang.instrument.IllegalClassFormatException;
   76.52 +import java.lang.instrument.Instrumentation;
   76.53 +import java.lang.instrument.UnmodifiableClassException;
   76.54 +import java.lang.reflect.InvocationTargetException;
   76.55 +import java.lang.reflect.Method;
   76.56 +import java.security.ProtectionDomain;
   76.57 +import java.util.Collection;
   76.58 +import java.util.HashSet;
   76.59 +import java.util.List;
   76.60 +import java.util.Set;
   76.61 +import java.util.concurrent.CopyOnWriteArrayList;
   76.62 +import java.util.jar.JarFile;
   76.63 +import java.util.logging.Level;
   76.64 +import java.util.logging.Logger;
   76.65 +
   76.66 +/**
   76.67 + *
   76.68 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   76.69 + */
   76.70 +final class NbInstrumentation implements Instrumentation {
   76.71 +    private static final Logger LOG = Logger.getLogger(NbInstrumentation.class.getName());
   76.72 +    private static final Object LOCK = new Object();
   76.73 +    private static volatile Collection<NbInstrumentation> ACTIVE;
   76.74 +
   76.75 +    private final List<ClassFileTransformer> transformers = new CopyOnWriteArrayList<ClassFileTransformer>();
   76.76 +    private static final ThreadLocal<Boolean> IN = new ThreadLocal<Boolean>();
   76.77 +    
   76.78 +    static NbInstrumentation registerAgent(ClassLoader l, String agentClassName) {
   76.79 +        try {
   76.80 +            return registerImpl(agentClassName, l);
   76.81 +        } catch (Throwable ex) {
   76.82 +            LOG.log(Level.WARNING, "Cannot register " + agentClassName, ex);
   76.83 +            return null;
   76.84 +        }
   76.85 +    }
   76.86 +    static void unregisterAgent(NbInstrumentation instr) {
   76.87 +        synchronized (LOCK) {
   76.88 +            if (ACTIVE != null) {
   76.89 +                Collection<NbInstrumentation> clone = new HashSet<NbInstrumentation>();
   76.90 +                clone.addAll(ACTIVE);
   76.91 +                clone.remove(instr);
   76.92 +                ACTIVE = clone;
   76.93 +            }
   76.94 +        }
   76.95 +    }
   76.96 +    private static NbInstrumentation registerImpl(String agentClassName, ClassLoader l) throws ClassNotFoundException, IllegalArgumentException, NoSuchMethodException, SecurityException, IllegalAccessException, InvocationTargetException {
   76.97 +        final NbInstrumentation inst = new NbInstrumentation();
   76.98 +        synchronized (LOCK) {
   76.99 +            if (ACTIVE == null) {
  76.100 +                ACTIVE = new HashSet<NbInstrumentation>();
  76.101 +            } else {
  76.102 +                Set<NbInstrumentation> s = new HashSet<NbInstrumentation>();
  76.103 +                s.addAll(ACTIVE);
  76.104 +                ACTIVE = s;
  76.105 +            }
  76.106 +            ACTIVE.add(inst);
  76.107 +        }
  76.108 +        Class<?> agentClass = Class.forName(agentClassName, true, l);
  76.109 +        try {
  76.110 +            Method m = agentClass.getMethod("agentmain", String.class, Instrumentation.class); // NOI18N
  76.111 +            m.invoke(null, "", inst);
  76.112 +        } catch (NoSuchMethodException ex) {
  76.113 +            Method m = agentClass.getMethod("agentmain", String.class); // NOI18N
  76.114 +            m.invoke(null, "");
  76.115 +        }
  76.116 +        return inst;
  76.117 +    }
  76.118 +    
  76.119 +    public static byte[] patchByteCode(ClassLoader l, String className, ProtectionDomain pd, byte[] arr) throws IllegalClassFormatException {
  76.120 +        if (ACTIVE == null) {
  76.121 +            return arr;
  76.122 +        }
  76.123 +        if (Boolean.TRUE.equals(IN.get())) {
  76.124 +            return arr;
  76.125 +        }
  76.126 +        try {
  76.127 +            IN.set(Boolean.TRUE);
  76.128 +            for (NbInstrumentation inst : ACTIVE) {
  76.129 +                for (ClassFileTransformer t : inst.transformers) {
  76.130 +                    arr = t.transform(l, className, null, pd, arr);
  76.131 +                }
  76.132 +            }
  76.133 +        } finally {
  76.134 +            IN.set(null);
  76.135 +        }
  76.136 +        return arr;
  76.137 +    }
  76.138 +    
  76.139 +    //
  76.140 +    // Instrumentation methods
  76.141 +    //
  76.142 +
  76.143 +    @Override
  76.144 +    public void addTransformer(ClassFileTransformer transformer, boolean canRetransform) {
  76.145 +        transformers.add(transformer);
  76.146 +    }
  76.147 +
  76.148 +    @Override
  76.149 +    public void addTransformer(ClassFileTransformer transformer) {
  76.150 +        transformers.add(transformer);
  76.151 +    }
  76.152 +
  76.153 +    @Override
  76.154 +    public boolean removeTransformer(ClassFileTransformer transformer) {
  76.155 +        return transformers.remove(transformer);
  76.156 +    }
  76.157 +
  76.158 +    @Override
  76.159 +    public boolean isRetransformClassesSupported() {
  76.160 +        return false;
  76.161 +    }
  76.162 +
  76.163 +    @Override
  76.164 +    public void retransformClasses(Class<?>... classes) throws UnmodifiableClassException {
  76.165 +        throw new UnmodifiableClassException();
  76.166 +    }
  76.167 +
  76.168 +    @Override
  76.169 +    public boolean isRedefineClassesSupported() {
  76.170 +        return false;
  76.171 +    }
  76.172 +
  76.173 +    @Override
  76.174 +    public void redefineClasses(ClassDefinition... definitions) throws ClassNotFoundException, UnmodifiableClassException {
  76.175 +        throw new UnmodifiableClassException();
  76.176 +    }
  76.177 +
  76.178 +    @Override
  76.179 +    public boolean isModifiableClass(Class<?> theClass) {
  76.180 +        return false;
  76.181 +    }
  76.182 +
  76.183 +    @Override
  76.184 +    public Class[] getAllLoadedClasses() {
  76.185 +        return new Class[0];
  76.186 +    }
  76.187 +
  76.188 +    @Override
  76.189 +    public Class[] getInitiatedClasses(ClassLoader loader) {
  76.190 +        return new Class[0];
  76.191 +    }
  76.192 +
  76.193 +    @Override
  76.194 +    public long getObjectSize(Object objectToSize) {
  76.195 +        return 42;
  76.196 +    }
  76.197 +
  76.198 +    @Override
  76.199 +    public void appendToBootstrapClassLoaderSearch(JarFile jarfile) {
  76.200 +    }
  76.201 +
  76.202 +    @Override
  76.203 +    public void appendToSystemClassLoaderSearch(JarFile jarfile) {
  76.204 +        throw new UnsupportedOperationException();
  76.205 +    }
  76.206 +
  76.207 +    @Override
  76.208 +    public boolean isNativeMethodPrefixSupported() {
  76.209 +        return false;
  76.210 +    }
  76.211 +
  76.212 +    @Override
  76.213 +    public void setNativeMethodPrefix(ClassFileTransformer transformer, String prefix) {
  76.214 +        throw new UnsupportedOperationException();
  76.215 +    }
  76.216 +    
  76.217 +}
    77.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    77.2 +++ b/equinox-agentclass-hook/src/main/resources/hookconfigurators.properties	Tue Jan 07 08:21:57 2014 +0100
    77.3 @@ -0,0 +1,44 @@
    77.4 +#
    77.5 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    77.6 +#
    77.7 +# Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    77.8 +#
    77.9 +# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   77.10 +# Other names may be trademarks of their respective owners.
   77.11 +#
   77.12 +# The contents of this file are subject to the terms of either the GNU
   77.13 +# General Public License Version 2 only ("GPL") or the Common
   77.14 +# Development and Distribution License("CDDL") (collectively, the
   77.15 +# "License"). You may not use this file except in compliance with the
   77.16 +# License. You can obtain a copy of the License at
   77.17 +# http://www.netbeans.org/cddl-gplv2.html
   77.18 +# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   77.19 +# specific language governing permissions and limitations under the
   77.20 +# License.  When distributing the software, include this License Header
   77.21 +# Notice in each file and include the License file at
   77.22 +# nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   77.23 +# particular file as subject to the "Classpath" exception as provided
   77.24 +# by Oracle in the GPL Version 2 section of the License file that
   77.25 +# accompanied this code. If applicable, add the following below the
   77.26 +# License Header, with the fields enclosed by brackets [] replaced by
   77.27 +# your own identifying information:
   77.28 +# "Portions Copyrighted [year] [name of copyright owner]"
   77.29 +#
   77.30 +# Contributor(s):
   77.31 +#
   77.32 +# The Original Software is NetBeans. The Initial Developer of the Original
   77.33 +# Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   77.34 +#
   77.35 +# If you wish your version of this file to be governed by only the CDDL
   77.36 +# or only the GPL Version 2, indicate your decision by adding
   77.37 +# "[Contributor] elects to include this software in this distribution
   77.38 +# under the [CDDL or GPL Version 2] license." If you do not indicate a
   77.39 +# single choice of license, a recipient has the option to distribute
   77.40 +# your version of this file under either the CDDL, the GPL Version 2 or
   77.41 +# to extend the choice of license to its licensees as provided above.
   77.42 +# However, if you add GPL Version 2 code and therefore, elected the GPL
   77.43 +# Version 2 license, then the option applies only if the new code is
   77.44 +# made subject to such option by the copyright holder.
   77.45 +#
   77.46 +
   77.47 +hook.configurators=org.netbeans.equinox.agentclass.AgentHook
    78.1 --- a/geo/pom.xml	Thu Dec 19 17:11:01 2013 +0100
    78.2 +++ b/geo/pom.xml	Tue Jan 07 08:21:57 2014 +0100
    78.3 @@ -2,11 +2,11 @@
    78.4  <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">
    78.5    <modelVersion>4.0.0</modelVersion>
    78.6    <parent>
    78.7 -    <groupId>org.apidesign</groupId>
    78.8 -    <artifactId>html</artifactId>
    78.9 +    <groupId>org.netbeans.html</groupId>
   78.10 +    <artifactId>pom</artifactId>
   78.11      <version>0.7-SNAPSHOT</version>
   78.12    </parent>
   78.13 -  <groupId>org.apidesign.html</groupId>
   78.14 +  <groupId>org.netbeans.html</groupId>
   78.15    <artifactId>net.java.html.geo</artifactId>
   78.16    <version>0.7-SNAPSHOT</version>
   78.17    <packaging>bundle</packaging>
   78.18 @@ -35,7 +35,7 @@
   78.19        <type>jar</type>
   78.20      </dependency>
   78.21      <dependency>
   78.22 -      <groupId>org.apidesign.html</groupId>
   78.23 +      <groupId>org.netbeans.html</groupId>
   78.24        <artifactId>net.java.html.boot</artifactId>
   78.25        <version>${project.version}</version>
   78.26        <type>jar</type>
    79.1 --- a/geo/src/main/java/net/java/html/geo/OnLocation.java	Thu Dec 19 17:11:01 2013 +0100
    79.2 +++ b/geo/src/main/java/net/java/html/geo/OnLocation.java	Tue Jan 07 08:21:57 2014 +0100
    79.3 @@ -1,22 +1,44 @@
    79.4  /**
    79.5 - * HTML via Java(tm) Language Bindings
    79.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    79.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    79.8   *
    79.9 - * This program is free software: you can redistribute it and/or modify
   79.10 - * it under the terms of the GNU General Public License as published by
   79.11 - * the Free Software Foundation, version 2 of the License.
   79.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   79.13   *
   79.14 - * This program is distributed in the hope that it will be useful,
   79.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   79.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   79.17 - * GNU General Public License for more details. apidesign.org
   79.18 - * designates this particular file as subject to the
   79.19 - * "Classpath" exception as provided by apidesign.org
   79.20 - * in the License file that accompanied this code.
   79.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   79.22 + * Other names may be trademarks of their respective owners.
   79.23   *
   79.24 - * You should have received a copy of the GNU General Public License
   79.25 - * along with this program. Look for COPYING file in the top folder.
   79.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   79.27 + * The contents of this file are subject to the terms of either the GNU
   79.28 + * General Public License Version 2 only ("GPL") or the Common
   79.29 + * Development and Distribution License("CDDL") (collectively, the
   79.30 + * "License"). You may not use this file except in compliance with the
   79.31 + * License. You can obtain a copy of the License at
   79.32 + * http://www.netbeans.org/cddl-gplv2.html
   79.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   79.34 + * specific language governing permissions and limitations under the
   79.35 + * License.  When distributing the software, include this License Header
   79.36 + * Notice in each file and include the License file at
   79.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   79.38 + * particular file as subject to the "Classpath" exception as provided
   79.39 + * by Oracle in the GPL Version 2 section of the License file that
   79.40 + * accompanied this code. If applicable, add the following below the
   79.41 + * License Header, with the fields enclosed by brackets [] replaced by
   79.42 + * your own identifying information:
   79.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   79.44 + *
   79.45 + * Contributor(s):
   79.46 + *
   79.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   79.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   79.49 + *
   79.50 + * If you wish your version of this file to be governed by only the CDDL
   79.51 + * or only the GPL Version 2, indicate your decision by adding
   79.52 + * "[Contributor] elects to include this software in this distribution
   79.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   79.54 + * single choice of license, a recipient has the option to distribute
   79.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   79.56 + * to extend the choice of license to its licensees as provided above.
   79.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   79.58 + * Version 2 license, then the option applies only if the new code is
   79.59 + * made subject to such option by the copyright holder.
   79.60   */
   79.61  package net.java.html.geo;
   79.62  
    80.1 --- a/geo/src/main/java/net/java/html/geo/Position.java	Thu Dec 19 17:11:01 2013 +0100
    80.2 +++ b/geo/src/main/java/net/java/html/geo/Position.java	Tue Jan 07 08:21:57 2014 +0100
    80.3 @@ -1,28 +1,50 @@
    80.4  /**
    80.5 - * HTML via Java(tm) Language Bindings
    80.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    80.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    80.8   *
    80.9 - * This program is free software: you can redistribute it and/or modify
   80.10 - * it under the terms of the GNU General Public License as published by
   80.11 - * the Free Software Foundation, version 2 of the License.
   80.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   80.13   *
   80.14 - * This program is distributed in the hope that it will be useful,
   80.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   80.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   80.17 - * GNU General Public License for more details. apidesign.org
   80.18 - * designates this particular file as subject to the
   80.19 - * "Classpath" exception as provided by apidesign.org
   80.20 - * in the License file that accompanied this code.
   80.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   80.22 + * Other names may be trademarks of their respective owners.
   80.23   *
   80.24 - * You should have received a copy of the GNU General Public License
   80.25 - * along with this program. Look for COPYING file in the top folder.
   80.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   80.27 + * The contents of this file are subject to the terms of either the GNU
   80.28 + * General Public License Version 2 only ("GPL") or the Common
   80.29 + * Development and Distribution License("CDDL") (collectively, the
   80.30 + * "License"). You may not use this file except in compliance with the
   80.31 + * License. You can obtain a copy of the License at
   80.32 + * http://www.netbeans.org/cddl-gplv2.html
   80.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   80.34 + * specific language governing permissions and limitations under the
   80.35 + * License.  When distributing the software, include this License Header
   80.36 + * Notice in each file and include the License file at
   80.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   80.38 + * particular file as subject to the "Classpath" exception as provided
   80.39 + * by Oracle in the GPL Version 2 section of the License file that
   80.40 + * accompanied this code. If applicable, add the following below the
   80.41 + * License Header, with the fields enclosed by brackets [] replaced by
   80.42 + * your own identifying information:
   80.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   80.44 + *
   80.45 + * Contributor(s):
   80.46 + *
   80.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   80.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   80.49 + *
   80.50 + * If you wish your version of this file to be governed by only the CDDL
   80.51 + * or only the GPL Version 2, indicate your decision by adding
   80.52 + * "[Contributor] elects to include this software in this distribution
   80.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   80.54 + * single choice of license, a recipient has the option to distribute
   80.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   80.56 + * to extend the choice of license to its licensees as provided above.
   80.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   80.58 + * Version 2 license, then the option applies only if the new code is
   80.59 + * made subject to such option by the copyright holder.
   80.60   */
   80.61  package net.java.html.geo;
   80.62  
   80.63  import java.util.logging.Level;
   80.64  import java.util.logging.Logger;
   80.65 -import org.apidesign.html.geo.impl.JsG;
   80.66 +import org.netbeans.html.geo.impl.JsG;
   80.67  
   80.68  /** Class that represents a geolocation position provided as a callback
   80.69   * to {@link Handle#onLocation(net.java.html.geo.Position)} method. The
    81.1 --- a/geo/src/main/java/net/java/html/geo/package.html	Thu Dec 19 17:11:01 2013 +0100
    81.2 +++ b/geo/src/main/java/net/java/html/geo/package.html	Tue Jan 07 08:21:57 2014 +0100
    81.3 @@ -1,23 +1,45 @@
    81.4  <!--
    81.5  
    81.6 -    HTML via Java(tm) Language Bindings
    81.7 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    81.8 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    81.9  
   81.10 -    This program is free software: you can redistribute it and/or modify
   81.11 -    it under the terms of the GNU General Public License as published by
   81.12 -    the Free Software Foundation, version 2 of the License.
   81.13 +    Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   81.14  
   81.15 -    This program is distributed in the hope that it will be useful,
   81.16 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   81.17 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   81.18 -    GNU General Public License for more details. apidesign.org
   81.19 -    designates this particular file as subject to the
   81.20 -    "Classpath" exception as provided by apidesign.org
   81.21 -    in the License file that accompanied this code.
   81.22 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   81.23 +    Other names may be trademarks of their respective owners.
   81.24  
   81.25 -    You should have received a copy of the GNU General Public License
   81.26 -    along with this program. Look for COPYING file in the top folder.
   81.27 -    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   81.28 +    The contents of this file are subject to the terms of either the GNU
   81.29 +    General Public License Version 2 only ("GPL") or the Common
   81.30 +    Development and Distribution License("CDDL") (collectively, the
   81.31 +    "License"). You may not use this file except in compliance with the
   81.32 +    License. You can obtain a copy of the License at
   81.33 +    http://www.netbeans.org/cddl-gplv2.html
   81.34 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   81.35 +    specific language governing permissions and limitations under the
   81.36 +    License.  When distributing the software, include this License Header
   81.37 +    Notice in each file and include the License file at
   81.38 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   81.39 +    particular file as subject to the "Classpath" exception as provided
   81.40 +    by Oracle in the GPL Version 2 section of the License file that
   81.41 +    accompanied this code. If applicable, add the following below the
   81.42 +    License Header, with the fields enclosed by brackets [] replaced by
   81.43 +    your own identifying information:
   81.44 +    "Portions Copyrighted [year] [name of copyright owner]"
   81.45 +
   81.46 +    Contributor(s):
   81.47 +
   81.48 +    The Original Software is NetBeans. The Initial Developer of the Original
   81.49 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   81.50 +
   81.51 +    If you wish your version of this file to be governed by only the CDDL
   81.52 +    or only the GPL Version 2, indicate your decision by adding
   81.53 +    "[Contributor] elects to include this software in this distribution
   81.54 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
   81.55 +    single choice of license, a recipient has the option to distribute
   81.56 +    your version of this file under either the CDDL, the GPL Version 2 or
   81.57 +    to extend the choice of license to its licensees as provided above.
   81.58 +    However, if you add GPL Version 2 code and therefore, elected the GPL
   81.59 +    Version 2 license, then the option applies only if the new code is
   81.60 +    made subject to such option by the copyright holder.
   81.61  
   81.62  -->
   81.63  <!DOCTYPE html>
    82.1 --- a/geo/src/main/java/org/apidesign/html/geo/impl/GeoProcessor.java	Thu Dec 19 17:11:01 2013 +0100
    82.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    82.3 @@ -1,267 +0,0 @@
    82.4 -/**
    82.5 - * HTML via Java(tm) Language Bindings
    82.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    82.7 - *
    82.8 - * This program is free software: you can redistribute it and/or modify
    82.9 - * it under the terms of the GNU General Public License as published by
   82.10 - * the Free Software Foundation, version 2 of the License.
   82.11 - *
   82.12 - * This program is distributed in the hope that it will be useful,
   82.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   82.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   82.15 - * GNU General Public License for more details. apidesign.org
   82.16 - * designates this particular file as subject to the
   82.17 - * "Classpath" exception as provided by apidesign.org
   82.18 - * in the License file that accompanied this code.
   82.19 - *
   82.20 - * You should have received a copy of the GNU General Public License
   82.21 - * along with this program. Look for COPYING file in the top folder.
   82.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   82.23 - */
   82.24 -package org.apidesign.html.geo.impl;
   82.25 -
   82.26 -import java.io.IOException;
   82.27 -import java.io.Writer;
   82.28 -import java.util.List;
   82.29 -import java.util.Locale;
   82.30 -import java.util.Set;
   82.31 -import java.util.logging.Level;
   82.32 -import java.util.logging.Logger;
   82.33 -import javax.annotation.processing.AbstractProcessor;
   82.34 -import javax.annotation.processing.Processor;
   82.35 -import javax.annotation.processing.RoundEnvironment;
   82.36 -import javax.annotation.processing.SupportedAnnotationTypes;
   82.37 -import javax.annotation.processing.SupportedSourceVersion;
   82.38 -import javax.lang.model.SourceVersion;
   82.39 -import javax.lang.model.element.Element;
   82.40 -import javax.lang.model.element.ElementKind;
   82.41 -import javax.lang.model.element.ExecutableElement;
   82.42 -import javax.lang.model.element.Modifier;
   82.43 -import javax.lang.model.element.PackageElement;
   82.44 -import javax.lang.model.element.TypeElement;
   82.45 -import javax.lang.model.element.VariableElement;
   82.46 -import javax.lang.model.type.TypeMirror;
   82.47 -import javax.tools.Diagnostic;
   82.48 -import javax.tools.JavaFileObject;
   82.49 -import net.java.html.geo.OnLocation;
   82.50 -import net.java.html.geo.Position;
   82.51 -import org.openide.util.lookup.ServiceProvider;
   82.52 -
   82.53 -/** Annotation processor to generate callbacks from {@link GeoHandle} class.
   82.54 - *
   82.55 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   82.56 - */
   82.57 -@ServiceProvider(service=Processor.class)
   82.58 -@SupportedSourceVersion(SourceVersion.RELEASE_6)
   82.59 -@SupportedAnnotationTypes({
   82.60 -    "net.java.html.geo.OnLocation"
   82.61 -})
   82.62 -public final class GeoProcessor extends AbstractProcessor {
   82.63 -    private static final Logger LOG = Logger.getLogger(GeoProcessor.class.getName());
   82.64 -    @Override
   82.65 -    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
   82.66 -        boolean ok = true;
   82.67 -        for (Element e : roundEnv.getElementsAnnotatedWith(OnLocation.class)) {
   82.68 -            if (!processLocation(e)) {
   82.69 -                ok = false;
   82.70 -            }
   82.71 -        }
   82.72 -        return ok;
   82.73 -    }
   82.74 -
   82.75 -    private void error(String msg, Element e) {
   82.76 -        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e);
   82.77 -    }
   82.78 -    
   82.79 -    private boolean processLocation(Element e) {
   82.80 -        if (e.getKind() != ElementKind.METHOD) {
   82.81 -            return false;
   82.82 -        }
   82.83 -        ExecutableElement me = (ExecutableElement) e;
   82.84 -        OnLocation ol = e.getAnnotation(OnLocation.class);
   82.85 -        if (ol == null) {
   82.86 -            return true;
   82.87 -        }
   82.88 -        if (me.getModifiers().contains(Modifier.PRIVATE)) {
   82.89 -            error("Method annotated by @OnLocation cannot be private", e);
   82.90 -            return false;
   82.91 -        }
   82.92 -        TypeMirror positionClass = processingEnv.getElementUtils().getTypeElement(Position.class.getName()).asType();
   82.93 -        final List<? extends VariableElement> params = me.getParameters();
   82.94 -        if (params.size() < 1 || !params.get(0).asType().equals(positionClass)) {
   82.95 -            error("Method annotated by @OnLocation first argument must be net.java.html.geo.Position!", e);
   82.96 -            return false;
   82.97 -        }
   82.98 -        String className = ol.className();
   82.99 -        if (className.isEmpty()) {
  82.100 -            String n = e.getSimpleName().toString();
  82.101 -            if (n.isEmpty()) {
  82.102 -                error("Empty method name", e);
  82.103 -                return false;
  82.104 -            }
  82.105 -            final String firstLetter = n.substring(0, 1).toUpperCase(Locale.ENGLISH);
  82.106 -            className = firstLetter + n.substring(1) + "Handle";
  82.107 -        }
  82.108 -        TypeElement te = (TypeElement)e.getEnclosingElement();
  82.109 -        PackageElement pe = (PackageElement) te.getEnclosingElement();
  82.110 -        final String pkg = pe.getQualifiedName().toString();
  82.111 -        final String fqn = pkg + "." + className;
  82.112 -        final boolean isStatic = me.getModifiers().contains(Modifier.STATIC);
  82.113 -        String sep;
  82.114 -        try {
  82.115 -            JavaFileObject fo = processingEnv.getFiler().createSourceFile(fqn, e);
  82.116 -            Writer w = fo.openWriter();
  82.117 -            w.append("package ").append(pkg).append(";\n");
  82.118 -            w.append("class ").append(className).append(" extends net.java.html.geo.Position.Handle {\n");
  82.119 -            if (!isStatic) {
  82.120 -                w.append("  private final ").append(te.getSimpleName()).append(" $i;\n");
  82.121 -            }
  82.122 -            for (int i = 1; i < params.size(); i++) {
  82.123 -                final VariableElement p = params.get(i);
  82.124 -                w.append("  private final ").append(p.asType().toString()).append(" ").append(p.getSimpleName()).append(";\n");
  82.125 -            }
  82.126 -            w.append("  private ").append(className).append("(boolean oneTime");
  82.127 -            w.append(", ").append(te.getSimpleName()).append(" i");
  82.128 -            for (int i = 1; i < params.size(); i++) {
  82.129 -                final VariableElement p = params.get(i);
  82.130 -                w.append(", ").append(p.asType().toString()).append(" ").append(p.getSimpleName());
  82.131 -            }
  82.132 -            w.append(") {\n    super(oneTime);\n");
  82.133 -            if (!isStatic) {
  82.134 -                w.append("    this.$i = i;\n");
  82.135 -            }
  82.136 -            for (int i = 1; i < params.size(); i++) {
  82.137 -                final VariableElement p = params.get(i);
  82.138 -                w.append("  this.").append(p.getSimpleName()).append(" = ").append(p.getSimpleName()).append(";\n");
  82.139 -            }
  82.140 -            w.append("}\n");
  82.141 -            w.append("  static net.java.html.geo.Position.Handle createQuery(");
  82.142 -            String inst;
  82.143 -            if (!isStatic) {
  82.144 -                w.append(te.getSimpleName()).append(" instance");
  82.145 -                inst = "instance";
  82.146 -                sep = ", ";
  82.147 -            } else {
  82.148 -                inst = "null";
  82.149 -                sep = "";
  82.150 -            }
  82.151 -            for (int i = 1; i < params.size(); i++) {
  82.152 -                final VariableElement p = params.get(i);
  82.153 -                w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName());
  82.154 -                sep = ", ";
  82.155 -            }
  82.156 -            w.append(") { return new ").append(className).append("(true, ").append(inst);
  82.157 -            for (int i = 1; i < params.size(); i++) {
  82.158 -                final VariableElement p = params.get(i);
  82.159 -                w.append(", ").append(p.getSimpleName());
  82.160 -            }
  82.161 -            w.append("); }\n");
  82.162 -            w.append("  static net.java.html.geo.Position.Handle createWatch(");
  82.163 -            if (!isStatic) {
  82.164 -                w.append(te.getSimpleName()).append(" instance");
  82.165 -                sep = ", ";
  82.166 -            } else {
  82.167 -                sep = "";
  82.168 -            }
  82.169 -            for (int i = 1; i < params.size(); i++) {
  82.170 -                final VariableElement p = params.get(i);
  82.171 -                w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName());
  82.172 -            }
  82.173 -            w.append(") { return new ").append(className).append("(false, ").append(inst);
  82.174 -            for (int i = 1; i < params.size(); i++) {
  82.175 -                final VariableElement p = params.get(i);
  82.176 -                w.append(", ").append(p.getSimpleName());
  82.177 -            }
  82.178 -            w.append("); }\n");
  82.179 -            w.append("  @Override protected void onError(Exception t) throws Throwable {\n");
  82.180 -            if (ol.onError().isEmpty()) {
  82.181 -                w.append("    t.printStackTrace();");
  82.182 -            } else {
  82.183 -                if (!findOnError(me, te, ol.onError(), isStatic)) {
  82.184 -                    return false;
  82.185 -                }
  82.186 -                if (isStatic) {
  82.187 -                    w.append("    ").append(te.getSimpleName()).append(".");
  82.188 -                } else {
  82.189 -                    w.append("    $i.");
  82.190 -                }
  82.191 -                w.append(ol.onError()).append("(t");
  82.192 -                for (int i = 1; i < params.size(); i++) {
  82.193 -                    final VariableElement p = params.get(i);
  82.194 -                    w.append(", ").append(p.getSimpleName());
  82.195 -                }
  82.196 -                w.append(");\n");
  82.197 -            }
  82.198 -            w.append("  }\n");
  82.199 -            w.append("  @Override protected void onLocation(net.java.html.geo.Position p) throws Throwable {\n");
  82.200 -            if (isStatic) {
  82.201 -                w.append("    ").append(te.getSimpleName()).append(".");
  82.202 -            } else {
  82.203 -                w.append("    $i.");
  82.204 -            }
  82.205 -            w.append(me.getSimpleName()).append("(p");
  82.206 -            for (int i = 1; i < params.size(); i++) {
  82.207 -                final VariableElement p = params.get(i);
  82.208 -                w.append(", ").append(p.getSimpleName());
  82.209 -            }
  82.210 -            w.append(");\n");
  82.211 -            w.append("  }\n");
  82.212 -            w.append("}\n");
  82.213 -            w.close();
  82.214 -        } catch (IOException ex) {
  82.215 -            Logger.getLogger(GeoProcessor.class.getName()).log(Level.SEVERE, null, ex);
  82.216 -            error("Can't write handler class: " + ex.getMessage(), e);
  82.217 -            return false;
  82.218 -        }
  82.219 -        
  82.220 -        return true;
  82.221 -    }
  82.222 -
  82.223 -    private boolean findOnError(ExecutableElement errElem, TypeElement te, String name, boolean onlyStatic) {
  82.224 -        String err = null;
  82.225 -        METHODS: for (Element e : te.getEnclosedElements()) {
  82.226 -            if (e.getKind() != ElementKind.METHOD) {
  82.227 -                continue;
  82.228 -            }
  82.229 -            if (!e.getSimpleName().contentEquals(name)) {
  82.230 -                continue;
  82.231 -            }
  82.232 -            if (onlyStatic && !e.getModifiers().contains(Modifier.STATIC)) {
  82.233 -                errElem = (ExecutableElement) e;
  82.234 -                err = "Would have to be static";
  82.235 -                continue;
  82.236 -            }
  82.237 -            ExecutableElement ee = (ExecutableElement) e;
  82.238 -            TypeMirror excType = processingEnv.getElementUtils().getTypeElement(Exception.class.getName()).asType();
  82.239 -            final List<? extends VariableElement> params = ee.getParameters(); 
  82.240 -            if (params.size() < 1 || 
  82.241 -                !processingEnv.getTypeUtils().isAssignable(excType, ee.getParameters().get(0).asType())
  82.242 -            ) {
  82.243 -                errElem = (ExecutableElement) e;
  82.244 -                err = "Error method first argument needs to be Exception";
  82.245 -                continue;
  82.246 -            }
  82.247 -            final List<? extends Element> origParams = errElem.getParameters();
  82.248 -            if (params.size() != origParams.size()) {
  82.249 -                errElem = (ExecutableElement) e;
  82.250 -                err = "Error method must have the same parameters as @OnLocation one";
  82.251 -                continue;
  82.252 -            }
  82.253 -            for (int i = 1; i < origParams.size(); i++) {
  82.254 -                final TypeMirror t1 = params.get(i).asType();
  82.255 -                final TypeMirror t2 = origParams.get(i).asType();
  82.256 -                if (!processingEnv.getTypeUtils().isSameType(t1, t2)) {
  82.257 -                    errElem = (ExecutableElement) e;
  82.258 -                    err = "Error method must have the same parameters as @OnLocation one";
  82.259 -                    continue METHODS;
  82.260 -                }
  82.261 -            }
  82.262 -            return true;
  82.263 -        }
  82.264 -        if (err == null) {
  82.265 -            err = "Cannot find " + name + "(Exception) method in this class";
  82.266 -        }
  82.267 -        error(err, errElem);
  82.268 -        return false;
  82.269 -    }
  82.270 -}
    83.1 --- a/geo/src/main/java/org/apidesign/html/geo/impl/JsG.java	Thu Dec 19 17:11:01 2013 +0100
    83.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    83.3 @@ -1,85 +0,0 @@
    83.4 -/**
    83.5 - * HTML via Java(tm) Language Bindings
    83.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    83.7 - *
    83.8 - * This program is free software: you can redistribute it and/or modify
    83.9 - * it under the terms of the GNU General Public License as published by
   83.10 - * the Free Software Foundation, version 2 of the License.
   83.11 - *
   83.12 - * This program is distributed in the hope that it will be useful,
   83.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   83.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   83.15 - * GNU General Public License for more details. apidesign.org
   83.16 - * designates this particular file as subject to the
   83.17 - * "Classpath" exception as provided by apidesign.org
   83.18 - * in the License file that accompanied this code.
   83.19 - *
   83.20 - * You should have received a copy of the GNU General Public License
   83.21 - * along with this program. Look for COPYING file in the top folder.
   83.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   83.23 - */
   83.24 -package org.apidesign.html.geo.impl;
   83.25 -
   83.26 -import net.java.html.js.JavaScriptBody;
   83.27 -
   83.28 -/** Implementation class to deal with browser's <code>navigator.geolocation</code> 
   83.29 - * object.
   83.30 - *
   83.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   83.32 - */
   83.33 -public abstract class JsG {
   83.34 -    protected JsG() {
   83.35 -        if (!getClass().getName().equals("net.java.html.geo.Position$Handle$JsH")) {
   83.36 -            throw new IllegalStateException();
   83.37 -        }
   83.38 -    }
   83.39 -    
   83.40 -    public abstract void onLocation(Object position);
   83.41 -    public abstract void onError(Object error);
   83.42 -    
   83.43 -    @JavaScriptBody(args = {}, body = "return !!navigator.geolocation;")
   83.44 -    public static boolean hasGeolocation() {
   83.45 -        return false;
   83.46 -    }
   83.47 -
   83.48 -    @JavaScriptBody(
   83.49 -        args = { "onlyOnce", "enableHighAccuracy", "timeout", "maximumAge" }, 
   83.50 -        javacall = true, 
   83.51 -        body = 
   83.52 -        "var self = this;\n" +
   83.53 -        "var ok = function (position) {\n" +
   83.54 -        "  self.@org.apidesign.html.geo.impl.JsG::onLocation(Ljava/lang/Object;)(position);\n" +
   83.55 -        "};\n" +
   83.56 -        "var fail = function (error) {\n" +
   83.57 -        "  self.@org.apidesign.html.geo.impl.JsG::onError(Ljava/lang/Object;)(error);\n" +
   83.58 -        "};\n" +
   83.59 -        "var options = {};\n" +
   83.60 -        "options.enableHighAccuracy = enableHighAccuracy;\n" +
   83.61 -        "if (timeout >= 0) options.timeout = timeout;\n" +
   83.62 -        "if (maximumAge >= 0) options.maximumAge = maximumAge;\n" +
   83.63 -        "if (onlyOnce) {\n" +
   83.64 -        "  navigator.geolocation.getCurrentPosition(ok, fail);\n" +
   83.65 -        "  return 0;\n" +
   83.66 -        "} else {\n" +
   83.67 -        "  return navigator.geolocation.watchPosition(ok, fail);\n" +
   83.68 -        "}\n"
   83.69 -    )
   83.70 -    protected long start(
   83.71 -        boolean onlyOnce, 
   83.72 -        boolean enableHighAccuracy,
   83.73 -        long timeout,
   83.74 -        long maximumAge
   83.75 -    ) {
   83.76 -        return -1;
   83.77 -    }
   83.78 -    
   83.79 -    @JavaScriptBody(args = { "watch" }, body = "navigator.geolocation.clearWatch(watch);")
   83.80 -    protected void stop(long watch) {
   83.81 -    }
   83.82 -
   83.83 -    @JavaScriptBody(args = { "self", "property" }, body = "return self[property];")
   83.84 -    public static Object get(Object self, String property) {
   83.85 -        return null;
   83.86 -    }
   83.87 -
   83.88 -}
    84.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    84.2 +++ b/geo/src/main/java/org/netbeans/html/geo/impl/GeoProcessor.java	Tue Jan 07 08:21:57 2014 +0100
    84.3 @@ -0,0 +1,289 @@
    84.4 +/**
    84.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    84.6 + *
    84.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    84.8 + *
    84.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   84.10 + * Other names may be trademarks of their respective owners.
   84.11 + *
   84.12 + * The contents of this file are subject to the terms of either the GNU
   84.13 + * General Public License Version 2 only ("GPL") or the Common
   84.14 + * Development and Distribution License("CDDL") (collectively, the
   84.15 + * "License"). You may not use this file except in compliance with the
   84.16 + * License. You can obtain a copy of the License at
   84.17 + * http://www.netbeans.org/cddl-gplv2.html
   84.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   84.19 + * specific language governing permissions and limitations under the
   84.20 + * License.  When distributing the software, include this License Header
   84.21 + * Notice in each file and include the License file at
   84.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   84.23 + * particular file as subject to the "Classpath" exception as provided
   84.24 + * by Oracle in the GPL Version 2 section of the License file that
   84.25 + * accompanied this code. If applicable, add the following below the
   84.26 + * License Header, with the fields enclosed by brackets [] replaced by
   84.27 + * your own identifying information:
   84.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   84.29 + *
   84.30 + * Contributor(s):
   84.31 + *
   84.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   84.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   84.34 + *
   84.35 + * If you wish your version of this file to be governed by only the CDDL
   84.36 + * or only the GPL Version 2, indicate your decision by adding
   84.37 + * "[Contributor] elects to include this software in this distribution
   84.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   84.39 + * single choice of license, a recipient has the option to distribute
   84.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   84.41 + * to extend the choice of license to its licensees as provided above.
   84.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   84.43 + * Version 2 license, then the option applies only if the new code is
   84.44 + * made subject to such option by the copyright holder.
   84.45 + */
   84.46 +package org.netbeans.html.geo.impl;
   84.47 +
   84.48 +import java.io.IOException;
   84.49 +import java.io.Writer;
   84.50 +import java.util.List;
   84.51 +import java.util.Locale;
   84.52 +import java.util.Set;
   84.53 +import java.util.logging.Level;
   84.54 +import java.util.logging.Logger;
   84.55 +import javax.annotation.processing.AbstractProcessor;
   84.56 +import javax.annotation.processing.Processor;
   84.57 +import javax.annotation.processing.RoundEnvironment;
   84.58 +import javax.annotation.processing.SupportedAnnotationTypes;
   84.59 +import javax.annotation.processing.SupportedSourceVersion;
   84.60 +import javax.lang.model.SourceVersion;
   84.61 +import javax.lang.model.element.Element;
   84.62 +import javax.lang.model.element.ElementKind;
   84.63 +import javax.lang.model.element.ExecutableElement;
   84.64 +import javax.lang.model.element.Modifier;
   84.65 +import javax.lang.model.element.PackageElement;
   84.66 +import javax.lang.model.element.TypeElement;
   84.67 +import javax.lang.model.element.VariableElement;
   84.68 +import javax.lang.model.type.TypeMirror;
   84.69 +import javax.tools.Diagnostic;
   84.70 +import javax.tools.JavaFileObject;
   84.71 +import net.java.html.geo.OnLocation;
   84.72 +import net.java.html.geo.Position;
   84.73 +import org.openide.util.lookup.ServiceProvider;
   84.74 +
   84.75 +/** Annotation processor to generate callbacks from {@link GeoHandle} class.
   84.76 + *
   84.77 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   84.78 + */
   84.79 +@ServiceProvider(service=Processor.class)
   84.80 +@SupportedSourceVersion(SourceVersion.RELEASE_6)
   84.81 +@SupportedAnnotationTypes({
   84.82 +    "net.java.html.geo.OnLocation"
   84.83 +})
   84.84 +public final class GeoProcessor extends AbstractProcessor {
   84.85 +    private static final Logger LOG = Logger.getLogger(GeoProcessor.class.getName());
   84.86 +    @Override
   84.87 +    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
   84.88 +        boolean ok = true;
   84.89 +        for (Element e : roundEnv.getElementsAnnotatedWith(OnLocation.class)) {
   84.90 +            if (!processLocation(e)) {
   84.91 +                ok = false;
   84.92 +            }
   84.93 +        }
   84.94 +        return ok;
   84.95 +    }
   84.96 +
   84.97 +    private void error(String msg, Element e) {
   84.98 +        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e);
   84.99 +    }
  84.100 +    
  84.101 +    private boolean processLocation(Element e) {
  84.102 +        if (e.getKind() != ElementKind.METHOD) {
  84.103 +            return false;
  84.104 +        }
  84.105 +        ExecutableElement me = (ExecutableElement) e;
  84.106 +        OnLocation ol = e.getAnnotation(OnLocation.class);
  84.107 +        if (ol == null) {
  84.108 +            return true;
  84.109 +        }
  84.110 +        if (me.getModifiers().contains(Modifier.PRIVATE)) {
  84.111 +            error("Method annotated by @OnLocation cannot be private", e);
  84.112 +            return false;
  84.113 +        }
  84.114 +        TypeMirror positionClass = processingEnv.getElementUtils().getTypeElement(Position.class.getName()).asType();
  84.115 +        final List<? extends VariableElement> params = me.getParameters();
  84.116 +        if (params.size() < 1 || !params.get(0).asType().equals(positionClass)) {
  84.117 +            error("Method annotated by @OnLocation first argument must be net.java.html.geo.Position!", e);
  84.118 +            return false;
  84.119 +        }
  84.120 +        String className = ol.className();
  84.121 +        if (className.isEmpty()) {
  84.122 +            String n = e.getSimpleName().toString();
  84.123 +            if (n.isEmpty()) {
  84.124 +                error("Empty method name", e);
  84.125 +                return false;
  84.126 +            }
  84.127 +            final String firstLetter = n.substring(0, 1).toUpperCase(Locale.ENGLISH);
  84.128 +            className = firstLetter + n.substring(1) + "Handle";
  84.129 +        }
  84.130 +        TypeElement te = (TypeElement)e.getEnclosingElement();
  84.131 +        PackageElement pe = (PackageElement) te.getEnclosingElement();
  84.132 +        final String pkg = pe.getQualifiedName().toString();
  84.133 +        final String fqn = pkg + "." + className;
  84.134 +        final boolean isStatic = me.getModifiers().contains(Modifier.STATIC);
  84.135 +        String sep;
  84.136 +        try {
  84.137 +            JavaFileObject fo = processingEnv.getFiler().createSourceFile(fqn, e);
  84.138 +            Writer w = fo.openWriter();
  84.139 +            w.append("package ").append(pkg).append(";\n");
  84.140 +            w.append("class ").append(className).append(" extends net.java.html.geo.Position.Handle {\n");
  84.141 +            if (!isStatic) {
  84.142 +                w.append("  private final ").append(te.getSimpleName()).append(" $i;\n");
  84.143 +            }
  84.144 +            for (int i = 1; i < params.size(); i++) {
  84.145 +                final VariableElement p = params.get(i);
  84.146 +                w.append("  private final ").append(p.asType().toString()).append(" ").append(p.getSimpleName()).append(";\n");
  84.147 +            }
  84.148 +            w.append("  private ").append(className).append("(boolean oneTime");
  84.149 +            w.append(", ").append(te.getSimpleName()).append(" i");
  84.150 +            for (int i = 1; i < params.size(); i++) {
  84.151 +                final VariableElement p = params.get(i);
  84.152 +                w.append(", ").append(p.asType().toString()).append(" ").append(p.getSimpleName());
  84.153 +            }
  84.154 +            w.append(") {\n    super(oneTime);\n");
  84.155 +            if (!isStatic) {
  84.156 +                w.append("    this.$i = i;\n");
  84.157 +            }
  84.158 +            for (int i = 1; i < params.size(); i++) {
  84.159 +                final VariableElement p = params.get(i);
  84.160 +                w.append("  this.").append(p.getSimpleName()).append(" = ").append(p.getSimpleName()).append(";\n");
  84.161 +            }
  84.162 +            w.append("}\n");
  84.163 +            w.append("  static net.java.html.geo.Position.Handle createQuery(");
  84.164 +            String inst;
  84.165 +            if (!isStatic) {
  84.166 +                w.append(te.getSimpleName()).append(" instance");
  84.167 +                inst = "instance";
  84.168 +                sep = ", ";
  84.169 +            } else {
  84.170 +                inst = "null";
  84.171 +                sep = "";
  84.172 +            }
  84.173 +            for (int i = 1; i < params.size(); i++) {
  84.174 +                final VariableElement p = params.get(i);
  84.175 +                w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName());
  84.176 +                sep = ", ";
  84.177 +            }
  84.178 +            w.append(") { return new ").append(className).append("(true, ").append(inst);
  84.179 +            for (int i = 1; i < params.size(); i++) {
  84.180 +                final VariableElement p = params.get(i);
  84.181 +                w.append(", ").append(p.getSimpleName());
  84.182 +            }
  84.183 +            w.append("); }\n");
  84.184 +            w.append("  static net.java.html.geo.Position.Handle createWatch(");
  84.185 +            if (!isStatic) {
  84.186 +                w.append(te.getSimpleName()).append(" instance");
  84.187 +                sep = ", ";
  84.188 +            } else {
  84.189 +                sep = "";
  84.190 +            }
  84.191 +            for (int i = 1; i < params.size(); i++) {
  84.192 +                final VariableElement p = params.get(i);
  84.193 +                w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName());
  84.194 +            }
  84.195 +            w.append(") { return new ").append(className).append("(false, ").append(inst);
  84.196 +            for (int i = 1; i < params.size(); i++) {
  84.197 +                final VariableElement p = params.get(i);
  84.198 +                w.append(", ").append(p.getSimpleName());
  84.199 +            }
  84.200 +            w.append("); }\n");
  84.201 +            w.append("  @Override protected void onError(Exception t) throws Throwable {\n");
  84.202 +            if (ol.onError().isEmpty()) {
  84.203 +                w.append("    t.printStackTrace();");
  84.204 +            } else {
  84.205 +                if (!findOnError(me, te, ol.onError(), isStatic)) {
  84.206 +                    return false;
  84.207 +                }
  84.208 +                if (isStatic) {
  84.209 +                    w.append("    ").append(te.getSimpleName()).append(".");
  84.210 +                } else {
  84.211 +                    w.append("    $i.");
  84.212 +                }
  84.213 +                w.append(ol.onError()).append("(t");
  84.214 +                for (int i = 1; i < params.size(); i++) {
  84.215 +                    final VariableElement p = params.get(i);
  84.216 +                    w.append(", ").append(p.getSimpleName());
  84.217 +                }
  84.218 +                w.append(");\n");
  84.219 +            }
  84.220 +            w.append("  }\n");
  84.221 +            w.append("  @Override protected void onLocation(net.java.html.geo.Position p) throws Throwable {\n");
  84.222 +            if (isStatic) {
  84.223 +                w.append("    ").append(te.getSimpleName()).append(".");
  84.224 +            } else {
  84.225 +                w.append("    $i.");
  84.226 +            }
  84.227 +            w.append(me.getSimpleName()).append("(p");
  84.228 +            for (int i = 1; i < params.size(); i++) {
  84.229 +                final VariableElement p = params.get(i);
  84.230 +                w.append(", ").append(p.getSimpleName());
  84.231 +            }
  84.232 +            w.append(");\n");
  84.233 +            w.append("  }\n");
  84.234 +            w.append("}\n");
  84.235 +            w.close();
  84.236 +        } catch (IOException ex) {
  84.237 +            Logger.getLogger(GeoProcessor.class.getName()).log(Level.SEVERE, null, ex);
  84.238 +            error("Can't write handler class: " + ex.getMessage(), e);
  84.239 +            return false;
  84.240 +        }
  84.241 +        
  84.242 +        return true;
  84.243 +    }
  84.244 +
  84.245 +    private boolean findOnError(ExecutableElement errElem, TypeElement te, String name, boolean onlyStatic) {
  84.246 +        String err = null;
  84.247 +        METHODS: for (Element e : te.getEnclosedElements()) {
  84.248 +            if (e.getKind() != ElementKind.METHOD) {
  84.249 +                continue;
  84.250 +            }
  84.251 +            if (!e.getSimpleName().contentEquals(name)) {
  84.252 +                continue;
  84.253 +            }
  84.254 +            if (onlyStatic && !e.getModifiers().contains(Modifier.STATIC)) {
  84.255 +                errElem = (ExecutableElement) e;
  84.256 +                err = "Would have to be static";
  84.257 +                continue;
  84.258 +            }
  84.259 +            ExecutableElement ee = (ExecutableElement) e;
  84.260 +            TypeMirror excType = processingEnv.getElementUtils().getTypeElement(Exception.class.getName()).asType();
  84.261 +            final List<? extends VariableElement> params = ee.getParameters(); 
  84.262 +            if (params.size() < 1 || 
  84.263 +                !processingEnv.getTypeUtils().isAssignable(excType, ee.getParameters().get(0).asType())
  84.264 +            ) {
  84.265 +                errElem = (ExecutableElement) e;
  84.266 +                err = "Error method first argument needs to be Exception";
  84.267 +                continue;
  84.268 +            }
  84.269 +            final List<? extends Element> origParams = errElem.getParameters();
  84.270 +            if (params.size() != origParams.size()) {
  84.271 +                errElem = (ExecutableElement) e;
  84.272 +                err = "Error method must have the same parameters as @OnLocation one";
  84.273 +                continue;
  84.274 +            }
  84.275 +            for (int i = 1; i < origParams.size(); i++) {
  84.276 +                final TypeMirror t1 = params.get(i).asType();
  84.277 +                final TypeMirror t2 = origParams.get(i).asType();
  84.278 +                if (!processingEnv.getTypeUtils().isSameType(t1, t2)) {
  84.279 +                    errElem = (ExecutableElement) e;
  84.280 +                    err = "Error method must have the same parameters as @OnLocation one";
  84.281 +                    continue METHODS;
  84.282 +                }
  84.283 +            }
  84.284 +            return true;
  84.285 +        }
  84.286 +        if (err == null) {
  84.287 +            err = "Cannot find " + name + "(Exception) method in this class";
  84.288 +        }
  84.289 +        error(err, errElem);
  84.290 +        return false;
  84.291 +    }
  84.292 +}
    85.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    85.2 +++ b/geo/src/main/java/org/netbeans/html/geo/impl/JsG.java	Tue Jan 07 08:21:57 2014 +0100
    85.3 @@ -0,0 +1,107 @@
    85.4 +/**
    85.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    85.6 + *
    85.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    85.8 + *
    85.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   85.10 + * Other names may be trademarks of their respective owners.
   85.11 + *
   85.12 + * The contents of this file are subject to the terms of either the GNU
   85.13 + * General Public License Version 2 only ("GPL") or the Common
   85.14 + * Development and Distribution License("CDDL") (collectively, the
   85.15 + * "License"). You may not use this file except in compliance with the
   85.16 + * License. You can obtain a copy of the License at
   85.17 + * http://www.netbeans.org/cddl-gplv2.html
   85.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   85.19 + * specific language governing permissions and limitations under the
   85.20 + * License.  When distributing the software, include this License Header
   85.21 + * Notice in each file and include the License file at
   85.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   85.23 + * particular file as subject to the "Classpath" exception as provided
   85.24 + * by Oracle in the GPL Version 2 section of the License file that
   85.25 + * accompanied this code. If applicable, add the following below the
   85.26 + * License Header, with the fields enclosed by brackets [] replaced by
   85.27 + * your own identifying information:
   85.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   85.29 + *
   85.30 + * Contributor(s):
   85.31 + *
   85.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   85.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   85.34 + *
   85.35 + * If you wish your version of this file to be governed by only the CDDL
   85.36 + * or only the GPL Version 2, indicate your decision by adding
   85.37 + * "[Contributor] elects to include this software in this distribution
   85.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   85.39 + * single choice of license, a recipient has the option to distribute
   85.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   85.41 + * to extend the choice of license to its licensees as provided above.
   85.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   85.43 + * Version 2 license, then the option applies only if the new code is
   85.44 + * made subject to such option by the copyright holder.
   85.45 + */
   85.46 +package org.netbeans.html.geo.impl;
   85.47 +
   85.48 +import net.java.html.js.JavaScriptBody;
   85.49 +
   85.50 +/** Implementation class to deal with browser's <code>navigator.geolocation</code> 
   85.51 + * object.
   85.52 + *
   85.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   85.54 + */
   85.55 +public abstract class JsG {
   85.56 +    protected JsG() {
   85.57 +        if (!getClass().getName().equals("net.java.html.geo.Position$Handle$JsH")) {
   85.58 +            throw new IllegalStateException();
   85.59 +        }
   85.60 +    }
   85.61 +    
   85.62 +    public abstract void onLocation(Object position);
   85.63 +    public abstract void onError(Object error);
   85.64 +    
   85.65 +    @JavaScriptBody(args = {}, body = "return !!navigator.geolocation;")
   85.66 +    public static boolean hasGeolocation() {
   85.67 +        return false;
   85.68 +    }
   85.69 +
   85.70 +    @JavaScriptBody(
   85.71 +        args = { "onlyOnce", "enableHighAccuracy", "timeout", "maximumAge" }, 
   85.72 +        javacall = true, 
   85.73 +        body = 
   85.74 +        "var self = this;\n" +
   85.75 +        "var ok = function (position) {\n" +
   85.76 +        "  self.@org.netbeans.html.geo.impl.JsG::onLocation(Ljava/lang/Object;)(position);\n" +
   85.77 +        "};\n" +
   85.78 +        "var fail = function (error) {\n" +
   85.79 +        "  self.@org.netbeans.html.geo.impl.JsG::onError(Ljava/lang/Object;)(error);\n" +
   85.80 +        "};\n" +
   85.81 +        "var options = {};\n" +
   85.82 +        "options.enableHighAccuracy = enableHighAccuracy;\n" +
   85.83 +        "if (timeout >= 0) options.timeout = timeout;\n" +
   85.84 +        "if (maximumAge >= 0) options.maximumAge = maximumAge;\n" +
   85.85 +        "if (onlyOnce) {\n" +
   85.86 +        "  navigator.geolocation.getCurrentPosition(ok, fail);\n" +
   85.87 +        "  return 0;\n" +
   85.88 +        "} else {\n" +
   85.89 +        "  return navigator.geolocation.watchPosition(ok, fail);\n" +
   85.90 +        "}\n"
   85.91 +    )
   85.92 +    protected long start(
   85.93 +        boolean onlyOnce, 
   85.94 +        boolean enableHighAccuracy,
   85.95 +        long timeout,
   85.96 +        long maximumAge
   85.97 +    ) {
   85.98 +        return -1;
   85.99 +    }
  85.100 +    
  85.101 +    @JavaScriptBody(args = { "watch" }, body = "navigator.geolocation.clearWatch(watch);")
  85.102 +    protected void stop(long watch) {
  85.103 +    }
  85.104 +
  85.105 +    @JavaScriptBody(args = { "self", "property" }, body = "return self[property];")
  85.106 +    public static Object get(Object self, String property) {
  85.107 +        return null;
  85.108 +    }
  85.109 +
  85.110 +}
    86.1 --- a/geo/src/test/java/net/java/html/geo/OnLocationTest.java	Thu Dec 19 17:11:01 2013 +0100
    86.2 +++ b/geo/src/test/java/net/java/html/geo/OnLocationTest.java	Tue Jan 07 08:21:57 2014 +0100
    86.3 @@ -1,22 +1,44 @@
    86.4  /**
    86.5 - * HTML via Java(tm) Language Bindings
    86.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    86.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    86.8   *
    86.9 - * This program is free software: you can redistribute it and/or modify
   86.10 - * it under the terms of the GNU General Public License as published by
   86.11 - * the Free Software Foundation, version 2 of the License.
   86.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   86.13   *
   86.14 - * This program is distributed in the hope that it will be useful,
   86.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   86.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   86.17 - * GNU General Public License for more details. apidesign.org
   86.18 - * designates this particular file as subject to the
   86.19 - * "Classpath" exception as provided by apidesign.org
   86.20 - * in the License file that accompanied this code.
   86.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   86.22 + * Other names may be trademarks of their respective owners.
   86.23   *
   86.24 - * You should have received a copy of the GNU General Public License
   86.25 - * along with this program. Look for COPYING file in the top folder.
   86.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   86.27 + * The contents of this file are subject to the terms of either the GNU
   86.28 + * General Public License Version 2 only ("GPL") or the Common
   86.29 + * Development and Distribution License("CDDL") (collectively, the
   86.30 + * "License"). You may not use this file except in compliance with the
   86.31 + * License. You can obtain a copy of the License at
   86.32 + * http://www.netbeans.org/cddl-gplv2.html
   86.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   86.34 + * specific language governing permissions and limitations under the
   86.35 + * License.  When distributing the software, include this License Header
   86.36 + * Notice in each file and include the License file at
   86.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   86.38 + * particular file as subject to the "Classpath" exception as provided
   86.39 + * by Oracle in the GPL Version 2 section of the License file that
   86.40 + * accompanied this code. If applicable, add the following below the
   86.41 + * License Header, with the fields enclosed by brackets [] replaced by
   86.42 + * your own identifying information:
   86.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   86.44 + *
   86.45 + * Contributor(s):
   86.46 + *
   86.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   86.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   86.49 + *
   86.50 + * If you wish your version of this file to be governed by only the CDDL
   86.51 + * or only the GPL Version 2, indicate your decision by adding
   86.52 + * "[Contributor] elects to include this software in this distribution
   86.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   86.54 + * single choice of license, a recipient has the option to distribute
   86.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   86.56 + * to extend the choice of license to its licensees as provided above.
   86.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   86.58 + * Version 2 license, then the option applies only if the new code is
   86.59 + * made subject to such option by the copyright holder.
   86.60   */
   86.61  package net.java.html.geo;
   86.62  
    87.1 --- a/geo/src/test/java/org/apidesign/html/geo/impl/Compile.java	Thu Dec 19 17:11:01 2013 +0100
    87.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    87.3 @@ -1,264 +0,0 @@
    87.4 -/**
    87.5 - * HTML via Java(tm) Language Bindings
    87.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    87.7 - *
    87.8 - * This program is free software: you can redistribute it and/or modify
    87.9 - * it under the terms of the GNU General Public License as published by
   87.10 - * the Free Software Foundation, version 2 of the License.
   87.11 - *
   87.12 - * This program is distributed in the hope that it will be useful,
   87.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   87.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   87.15 - * GNU General Public License for more details. apidesign.org
   87.16 - * designates this particular file as subject to the
   87.17 - * "Classpath" exception as provided by apidesign.org
   87.18 - * in the License file that accompanied this code.
   87.19 - *
   87.20 - * You should have received a copy of the GNU General Public License
   87.21 - * along with this program. Look for COPYING file in the top folder.
   87.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   87.23 - */
   87.24 -package org.apidesign.html.geo.impl;
   87.25 -
   87.26 -import java.io.ByteArrayInputStream;
   87.27 -import java.io.ByteArrayOutputStream;
   87.28 -import java.io.IOException;
   87.29 -import java.io.InputStream;
   87.30 -import java.io.OutputStream;
   87.31 -import java.net.URI;
   87.32 -import java.net.URISyntaxException;
   87.33 -import java.util.ArrayList;
   87.34 -import java.util.Arrays;
   87.35 -import java.util.HashMap;
   87.36 -import java.util.List;
   87.37 -import java.util.Locale;
   87.38 -import java.util.Map;
   87.39 -import java.util.regex.Matcher;
   87.40 -import java.util.regex.Pattern;
   87.41 -import javax.tools.Diagnostic;
   87.42 -import javax.tools.DiagnosticListener;
   87.43 -import javax.tools.FileObject;
   87.44 -import javax.tools.ForwardingJavaFileManager;
   87.45 -import javax.tools.JavaFileManager;
   87.46 -import javax.tools.JavaFileObject;
   87.47 -import javax.tools.JavaFileObject.Kind;
   87.48 -import javax.tools.SimpleJavaFileObject;
   87.49 -import javax.tools.StandardJavaFileManager;
   87.50 -import javax.tools.StandardLocation;
   87.51 -import javax.tools.ToolProvider;
   87.52 -import static org.testng.Assert.*;
   87.53 -
   87.54 -/**
   87.55 - *
   87.56 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   87.57 - */
   87.58 -final class Compile implements DiagnosticListener<JavaFileObject> {
   87.59 -    private final List<Diagnostic<? extends JavaFileObject>> errors = 
   87.60 -            new ArrayList<Diagnostic<? extends JavaFileObject>>();
   87.61 -    private final Map<String, byte[]> classes;
   87.62 -    private final String pkg;
   87.63 -    private final String cls;
   87.64 -    private final String html;
   87.65 -    private final String sourceLevel;
   87.66 -
   87.67 -    private Compile(String html, String code, String sl) throws IOException {
   87.68 -        this.pkg = findPkg(code);
   87.69 -        this.cls = findCls(code);
   87.70 -        this.html = html;
   87.71 -        this.sourceLevel = sl;
   87.72 -        classes = compile(html, code);
   87.73 -    }
   87.74 -
   87.75 -    /** Performs compilation of given HTML page and associated Java code
   87.76 -     */
   87.77 -    public static Compile create(String html, String code) throws IOException {
   87.78 -        return create(html, code, "1.7");
   87.79 -    }
   87.80 -    static Compile create(String html, String code, String sourceLevel) throws IOException {
   87.81 -        return new Compile(html, code, sourceLevel);
   87.82 -    }
   87.83 -    
   87.84 -    /** Checks for given class among compiled resources */
   87.85 -    public byte[] get(String res) {
   87.86 -        return classes.get(res);
   87.87 -    }
   87.88 -    
   87.89 -    /** Obtains errors created during compilation.
   87.90 -     */
   87.91 -    public List<Diagnostic<? extends JavaFileObject>> getErrors() {
   87.92 -        List<Diagnostic<? extends JavaFileObject>> err;
   87.93 -        err = new ArrayList<Diagnostic<? extends JavaFileObject>>();
   87.94 -        for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
   87.95 -            if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
   87.96 -                err.add(diagnostic);
   87.97 -            }
   87.98 -        }
   87.99 -        return err;
  87.100 -    }
  87.101 -    
  87.102 -    private Map<String, byte[]> compile(final String html, final String code) throws IOException {
  87.103 -        StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
  87.104 -
  87.105 -        final Map<String, ByteArrayOutputStream> class2BAOS;
  87.106 -        class2BAOS = new HashMap<String, ByteArrayOutputStream>();
  87.107 -
  87.108 -        JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
  87.109 -            @Override
  87.110 -            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  87.111 -                return code;
  87.112 -            }
  87.113 -        };
  87.114 -        final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
  87.115 -            @Override
  87.116 -            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  87.117 -                return html;
  87.118 -            }
  87.119 -
  87.120 -            @Override
  87.121 -            public InputStream openInputStream() throws IOException {
  87.122 -                return new ByteArrayInputStream(html.getBytes());
  87.123 -            }
  87.124 -        };
  87.125 -        
  87.126 -        final URI scratch;
  87.127 -        try {
  87.128 -            scratch = new URI("mem://mem3");
  87.129 -        } catch (URISyntaxException ex) {
  87.130 -            throw new IOException(ex);
  87.131 -        }
  87.132 -        
  87.133 -        JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
  87.134 -            @Override
  87.135 -            public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
  87.136 -                if (kind  == Kind.CLASS) {
  87.137 -                    final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
  87.138 -
  87.139 -                    class2BAOS.put(className.replace('.', '/') + ".class", buffer);
  87.140 -                    return new SimpleJavaFileObject(sibling.toUri(), kind) {
  87.141 -                        @Override
  87.142 -                        public OutputStream openOutputStream() throws IOException {
  87.143 -                            return buffer;
  87.144 -                        }
  87.145 -                    };
  87.146 -                }
  87.147 -                
  87.148 -                if (kind == Kind.SOURCE) {
  87.149 -                    final String n = className.replace('.', '/') + ".java";
  87.150 -                    final URI un;
  87.151 -                    try {
  87.152 -                        un = new URI("mem://" + n);
  87.153 -                    } catch (URISyntaxException ex) {
  87.154 -                        throw new IOException(ex);
  87.155 -                    }
  87.156 -                    return new VirtFO(un/*sibling.toUri()*/, kind, n);
  87.157 -                }
  87.158 -                
  87.159 -                throw new IllegalStateException();
  87.160 -            }
  87.161 -
  87.162 -            @Override
  87.163 -            public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
  87.164 -                if (location == StandardLocation.SOURCE_PATH) {
  87.165 -                    if (packageName.equals(pkg)) {
  87.166 -                        return htmlFile;
  87.167 -                    }
  87.168 -                }
  87.169 -                
  87.170 -                return null;
  87.171 -            }
  87.172 -
  87.173 -            @Override
  87.174 -            public boolean isSameFile(FileObject a, FileObject b) {
  87.175 -                if (a instanceof VirtFO && b instanceof VirtFO) {
  87.176 -                    return ((VirtFO)a).getName().equals(((VirtFO)b).getName());
  87.177 -                }
  87.178 -                
  87.179 -                return super.isSameFile(a, b);
  87.180 -            }
  87.181 -
  87.182 -            class VirtFO extends SimpleJavaFileObject {
  87.183 -
  87.184 -                private final String n;
  87.185 -
  87.186 -                public VirtFO(URI uri, Kind kind, String n) {
  87.187 -                    super(uri, kind);
  87.188 -                    this.n = n;
  87.189 -                }
  87.190 -                private final ByteArrayOutputStream data = new ByteArrayOutputStream();
  87.191 -
  87.192 -                @Override
  87.193 -                public OutputStream openOutputStream() throws IOException {
  87.194 -                    return data;
  87.195 -                }
  87.196 -
  87.197 -                @Override
  87.198 -                public String getName() {
  87.199 -                    return n;
  87.200 -                }
  87.201 -
  87.202 -                @Override
  87.203 -                public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  87.204 -                    data.close();
  87.205 -                    return new String(data.toByteArray());
  87.206 -                }
  87.207 -            }
  87.208 -        };
  87.209 -
  87.210 -        ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", sourceLevel, "-target", "1.7"), null, Arrays.asList(file)).call();
  87.211 -
  87.212 -        Map<String, byte[]> result = new HashMap<String, byte[]>();
  87.213 -
  87.214 -        for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
  87.215 -            result.put(e.getKey(), e.getValue().toByteArray());
  87.216 -        }
  87.217 -
  87.218 -        return result;
  87.219 -    }
  87.220 -
  87.221 -
  87.222 -    @Override
  87.223 -    public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
  87.224 -        errors.add(diagnostic);
  87.225 -    }
  87.226 -    private static String findPkg(String java) throws IOException {
  87.227 -        Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
  87.228 -        Matcher m = p.matcher(java);
  87.229 -        if (!m.find()) {
  87.230 -            throw new IOException("Can't find package declaration in the java file");
  87.231 -        }
  87.232 -        String pkg = m.group(1);
  87.233 -        return pkg;
  87.234 -    }
  87.235 -    private static String findCls(String java) throws IOException {
  87.236 -        Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
  87.237 -        Matcher m = p.matcher(java);
  87.238 -        if (!m.find()) {
  87.239 -            throw new IOException("Can't find package declaration in the java file");
  87.240 -        }
  87.241 -        String cls = m.group(1);
  87.242 -        return cls;
  87.243 -    }
  87.244 -
  87.245 -    String getHtml() {
  87.246 -        String fqn = "'" + pkg + '.' + cls + "'";
  87.247 -        return html.replace("'${fqn}'", fqn);
  87.248 -    }
  87.249 -
  87.250 -    void assertErrors() {
  87.251 -        assertFalse(getErrors().isEmpty(), "There are supposed to be some errors");
  87.252 -    }
  87.253 -
  87.254 -    void assertError(String expMsg) {
  87.255 -        StringBuilder sb = new StringBuilder();
  87.256 -        sb.append("Can't find ").append(expMsg).append(" among:");
  87.257 -        for (Diagnostic<? extends JavaFileObject> e : errors) {
  87.258 -            String msg = e.getMessage(Locale.US);
  87.259 -            if (msg.contains(expMsg)) {
  87.260 -                return;
  87.261 -            }
  87.262 -            sb.append("\n");
  87.263 -            sb.append(msg);
  87.264 -        }
  87.265 -        fail(sb.toString());
  87.266 -    }
  87.267 -}
    88.1 --- a/geo/src/test/java/org/apidesign/html/geo/impl/GeoProcessorTest.java	Thu Dec 19 17:11:01 2013 +0100
    88.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    88.3 @@ -1,92 +0,0 @@
    88.4 -/**
    88.5 - * HTML via Java(tm) Language Bindings
    88.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    88.7 - *
    88.8 - * This program is free software: you can redistribute it and/or modify
    88.9 - * it under the terms of the GNU General Public License as published by
   88.10 - * the Free Software Foundation, version 2 of the License.
   88.11 - *
   88.12 - * This program is distributed in the hope that it will be useful,
   88.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   88.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   88.15 - * GNU General Public License for more details. apidesign.org
   88.16 - * designates this particular file as subject to the
   88.17 - * "Classpath" exception as provided by apidesign.org
   88.18 - * in the License file that accompanied this code.
   88.19 - *
   88.20 - * You should have received a copy of the GNU General Public License
   88.21 - * along with this program. Look for COPYING file in the top folder.
   88.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   88.23 - */
   88.24 -package org.apidesign.html.geo.impl;
   88.25 -
   88.26 -import java.io.IOException;
   88.27 -import org.testng.annotations.Test;
   88.28 -
   88.29 -/** Test whether the annotation processor detects errors correctly.
   88.30 - *
   88.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   88.32 - */
   88.33 -public class GeoProcessorTest {
   88.34 -    
   88.35 -    public GeoProcessorTest() {
   88.36 -    }
   88.37 -
   88.38 -    @Test public void onLocationMethodHasToTakePositionParameter() throws IOException {
   88.39 -        Compile res = Compile.create("", "package x;\n"
   88.40 -            + "class UseOnLocation {\n"
   88.41 -            + "  @net.java.html.geo.OnLocation\n"
   88.42 -            + "  public static void cantCallMe() {}\n"
   88.43 -            + "}\n"
   88.44 -        );
   88.45 -        res.assertErrors();
   88.46 -        res.assertError("first argument must be net.java.html.geo.Position");
   88.47 -    }
   88.48 -    
   88.49 -    @Test public void onLocationMethodCannotBePrivate() throws IOException {
   88.50 -        Compile res = Compile.create("", "package x;\n"
   88.51 -            + "class UseOnLocation {\n"
   88.52 -            + "  @net.java.html.geo.OnLocation\n"
   88.53 -            + "  private static void cantCallMe(net.java.html.geo.Position p) {}\n"
   88.54 -            + "}\n"
   88.55 -        );
   88.56 -        res.assertErrors();
   88.57 -        res.assertError("cannot be private");
   88.58 -    }
   88.59 -    
   88.60 -    @Test public void onErrorHasToExist() throws IOException {
   88.61 -        Compile res = Compile.create("", "package x;\n"
   88.62 -            + "class UseOnLocation {\n"
   88.63 -            + "  @net.java.html.geo.OnLocation(onError=\"doesNotExist\")\n"
   88.64 -            + "  static void cantCallMe(net.java.html.geo.Position p) {}\n"
   88.65 -            + "}\n"
   88.66 -        );
   88.67 -        res.assertErrors();
   88.68 -        res.assertError("not find doesNotExist");
   88.69 -    }
   88.70 -
   88.71 -    @Test public void onErrorWouldHaveToBeStatic() throws IOException {
   88.72 -        Compile res = Compile.create("", "package x;\n"
   88.73 -            + "class UseOnLocation {\n"
   88.74 -            + "  @net.java.html.geo.OnLocation(onError=\"notStatic\")\n"
   88.75 -            + "  static void cantCallMe(net.java.html.geo.Position p) {}\n"
   88.76 -            + "  void notStatic(Exception e) {}\n"
   88.77 -            + "}\n"
   88.78 -        );
   88.79 -        res.assertErrors();
   88.80 -        res.assertError("have to be static");
   88.81 -    }
   88.82 -
   88.83 -    @Test public void onErrorMustAcceptExceptionArgument() throws IOException {
   88.84 -        Compile res = Compile.create("", "package x;\n"
   88.85 -            + "class UseOnLocation {\n"
   88.86 -            + "  @net.java.html.geo.OnLocation(onError=\"notStatic\")\n"
   88.87 -            + "  static void cantCallMe(net.java.html.geo.Position p) {}\n"
   88.88 -            + "  static void notStatic(java.io.IOException e) {}\n"
   88.89 -            + "}\n"
   88.90 -        );
   88.91 -        res.assertErrors();
   88.92 -        res.assertError("Error method first argument needs to be Exception");
   88.93 -    }
   88.94 -    
   88.95 -}
    89.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    89.2 +++ b/geo/src/test/java/org/netbeans/html/geo/impl/Compile.java	Tue Jan 07 08:21:57 2014 +0100
    89.3 @@ -0,0 +1,286 @@
    89.4 +/**
    89.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    89.6 + *
    89.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    89.8 + *
    89.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   89.10 + * Other names may be trademarks of their respective owners.
   89.11 + *
   89.12 + * The contents of this file are subject to the terms of either the GNU
   89.13 + * General Public License Version 2 only ("GPL") or the Common
   89.14 + * Development and Distribution License("CDDL") (collectively, the
   89.15 + * "License"). You may not use this file except in compliance with the
   89.16 + * License. You can obtain a copy of the License at
   89.17 + * http://www.netbeans.org/cddl-gplv2.html
   89.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   89.19 + * specific language governing permissions and limitations under the
   89.20 + * License.  When distributing the software, include this License Header
   89.21 + * Notice in each file and include the License file at
   89.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   89.23 + * particular file as subject to the "Classpath" exception as provided
   89.24 + * by Oracle in the GPL Version 2 section of the License file that
   89.25 + * accompanied this code. If applicable, add the following below the
   89.26 + * License Header, with the fields enclosed by brackets [] replaced by
   89.27 + * your own identifying information:
   89.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   89.29 + *
   89.30 + * Contributor(s):
   89.31 + *
   89.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   89.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   89.34 + *
   89.35 + * If you wish your version of this file to be governed by only the CDDL
   89.36 + * or only the GPL Version 2, indicate your decision by adding
   89.37 + * "[Contributor] elects to include this software in this distribution
   89.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   89.39 + * single choice of license, a recipient has the option to distribute
   89.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   89.41 + * to extend the choice of license to its licensees as provided above.
   89.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   89.43 + * Version 2 license, then the option applies only if the new code is
   89.44 + * made subject to such option by the copyright holder.
   89.45 + */
   89.46 +package org.netbeans.html.geo.impl;
   89.47 +
   89.48 +import java.io.ByteArrayInputStream;
   89.49 +import java.io.ByteArrayOutputStream;
   89.50 +import java.io.IOException;
   89.51 +import java.io.InputStream;
   89.52 +import java.io.OutputStream;
   89.53 +import java.net.URI;
   89.54 +import java.net.URISyntaxException;
   89.55 +import java.util.ArrayList;
   89.56 +import java.util.Arrays;
   89.57 +import java.util.HashMap;
   89.58 +import java.util.List;
   89.59 +import java.util.Locale;
   89.60 +import java.util.Map;
   89.61 +import java.util.regex.Matcher;
   89.62 +import java.util.regex.Pattern;
   89.63 +import javax.tools.Diagnostic;
   89.64 +import javax.tools.DiagnosticListener;
   89.65 +import javax.tools.FileObject;
   89.66 +import javax.tools.ForwardingJavaFileManager;
   89.67 +import javax.tools.JavaFileManager;
   89.68 +import javax.tools.JavaFileObject;
   89.69 +import javax.tools.JavaFileObject.Kind;
   89.70 +import javax.tools.SimpleJavaFileObject;
   89.71 +import javax.tools.StandardJavaFileManager;
   89.72 +import javax.tools.StandardLocation;
   89.73 +import javax.tools.ToolProvider;
   89.74 +import static org.testng.Assert.*;
   89.75 +
   89.76 +/**
   89.77 + *
   89.78 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   89.79 + */
   89.80 +final class Compile implements DiagnosticListener<JavaFileObject> {
   89.81 +    private final List<Diagnostic<? extends JavaFileObject>> errors = 
   89.82 +            new ArrayList<Diagnostic<? extends JavaFileObject>>();
   89.83 +    private final Map<String, byte[]> classes;
   89.84 +    private final String pkg;
   89.85 +    private final String cls;
   89.86 +    private final String html;
   89.87 +    private final String sourceLevel;
   89.88 +
   89.89 +    private Compile(String html, String code, String sl) throws IOException {
   89.90 +        this.pkg = findPkg(code);
   89.91 +        this.cls = findCls(code);
   89.92 +        this.html = html;
   89.93 +        this.sourceLevel = sl;
   89.94 +        classes = compile(html, code);
   89.95 +    }
   89.96 +
   89.97 +    /** Performs compilation of given HTML page and associated Java code
   89.98 +     */
   89.99 +    public static Compile create(String html, String code) throws IOException {
  89.100 +        return create(html, code, "1.7");
  89.101 +    }
  89.102 +    static Compile create(String html, String code, String sourceLevel) throws IOException {
  89.103 +        return new Compile(html, code, sourceLevel);
  89.104 +    }
  89.105 +    
  89.106 +    /** Checks for given class among compiled resources */
  89.107 +    public byte[] get(String res) {
  89.108 +        return classes.get(res);
  89.109 +    }
  89.110 +    
  89.111 +    /** Obtains errors created during compilation.
  89.112 +     */
  89.113 +    public List<Diagnostic<? extends JavaFileObject>> getErrors() {
  89.114 +        List<Diagnostic<? extends JavaFileObject>> err;
  89.115 +        err = new ArrayList<Diagnostic<? extends JavaFileObject>>();
  89.116 +        for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
  89.117 +            if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
  89.118 +                err.add(diagnostic);
  89.119 +            }
  89.120 +        }
  89.121 +        return err;
  89.122 +    }
  89.123 +    
  89.124 +    private Map<String, byte[]> compile(final String html, final String code) throws IOException {
  89.125 +        StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
  89.126 +
  89.127 +        final Map<String, ByteArrayOutputStream> class2BAOS;
  89.128 +        class2BAOS = new HashMap<String, ByteArrayOutputStream>();
  89.129 +
  89.130 +        JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
  89.131 +            @Override
  89.132 +            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  89.133 +                return code;
  89.134 +            }
  89.135 +        };
  89.136 +        final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
  89.137 +            @Override
  89.138 +            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  89.139 +                return html;
  89.140 +            }
  89.141 +
  89.142 +            @Override
  89.143 +            public InputStream openInputStream() throws IOException {
  89.144 +                return new ByteArrayInputStream(html.getBytes());
  89.145 +            }
  89.146 +        };
  89.147 +        
  89.148 +        final URI scratch;
  89.149 +        try {
  89.150 +            scratch = new URI("mem://mem3");
  89.151 +        } catch (URISyntaxException ex) {
  89.152 +            throw new IOException(ex);
  89.153 +        }
  89.154 +        
  89.155 +        JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
  89.156 +            @Override
  89.157 +            public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
  89.158 +                if (kind  == Kind.CLASS) {
  89.159 +                    final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
  89.160 +
  89.161 +                    class2BAOS.put(className.replace('.', '/') + ".class", buffer);
  89.162 +                    return new SimpleJavaFileObject(sibling.toUri(), kind) {
  89.163 +                        @Override
  89.164 +                        public OutputStream openOutputStream() throws IOException {
  89.165 +                            return buffer;
  89.166 +                        }
  89.167 +                    };
  89.168 +                }
  89.169 +                
  89.170 +                if (kind == Kind.SOURCE) {
  89.171 +                    final String n = className.replace('.', '/') + ".java";
  89.172 +                    final URI un;
  89.173 +                    try {
  89.174 +                        un = new URI("mem://" + n);
  89.175 +                    } catch (URISyntaxException ex) {
  89.176 +                        throw new IOException(ex);
  89.177 +                    }
  89.178 +                    return new VirtFO(un/*sibling.toUri()*/, kind, n);
  89.179 +                }
  89.180 +                
  89.181 +                throw new IllegalStateException();
  89.182 +            }
  89.183 +
  89.184 +            @Override
  89.185 +            public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
  89.186 +                if (location == StandardLocation.SOURCE_PATH) {
  89.187 +                    if (packageName.equals(pkg)) {
  89.188 +                        return htmlFile;
  89.189 +                    }
  89.190 +                }
  89.191 +                
  89.192 +                return null;
  89.193 +            }
  89.194 +
  89.195 +            @Override
  89.196 +            public boolean isSameFile(FileObject a, FileObject b) {
  89.197 +                if (a instanceof VirtFO && b instanceof VirtFO) {
  89.198 +                    return ((VirtFO)a).getName().equals(((VirtFO)b).getName());
  89.199 +                }
  89.200 +                
  89.201 +                return super.isSameFile(a, b);
  89.202 +            }
  89.203 +
  89.204 +            class VirtFO extends SimpleJavaFileObject {
  89.205 +
  89.206 +                private final String n;
  89.207 +
  89.208 +                public VirtFO(URI uri, Kind kind, String n) {
  89.209 +                    super(uri, kind);
  89.210 +                    this.n = n;
  89.211 +                }
  89.212 +                private final ByteArrayOutputStream data = new ByteArrayOutputStream();
  89.213 +
  89.214 +                @Override
  89.215 +                public OutputStream openOutputStream() throws IOException {
  89.216 +                    return data;
  89.217 +                }
  89.218 +
  89.219 +                @Override
  89.220 +                public String getName() {
  89.221 +                    return n;
  89.222 +                }
  89.223 +
  89.224 +                @Override
  89.225 +                public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  89.226 +                    data.close();
  89.227 +                    return new String(data.toByteArray());
  89.228 +                }
  89.229 +            }
  89.230 +        };
  89.231 +
  89.232 +        ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", sourceLevel, "-target", "1.7"), null, Arrays.asList(file)).call();
  89.233 +
  89.234 +        Map<String, byte[]> result = new HashMap<String, byte[]>();
  89.235 +
  89.236 +        for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
  89.237 +            result.put(e.getKey(), e.getValue().toByteArray());
  89.238 +        }
  89.239 +
  89.240 +        return result;
  89.241 +    }
  89.242 +
  89.243 +
  89.244 +    @Override
  89.245 +    public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
  89.246 +        errors.add(diagnostic);
  89.247 +    }
  89.248 +    private static String findPkg(String java) throws IOException {
  89.249 +        Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
  89.250 +        Matcher m = p.matcher(java);
  89.251 +        if (!m.find()) {
  89.252 +            throw new IOException("Can't find package declaration in the java file");
  89.253 +        }
  89.254 +        String pkg = m.group(1);
  89.255 +        return pkg;
  89.256 +    }
  89.257 +    private static String findCls(String java) throws IOException {
  89.258 +        Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
  89.259 +        Matcher m = p.matcher(java);
  89.260 +        if (!m.find()) {
  89.261 +            throw new IOException("Can't find package declaration in the java file");
  89.262 +        }
  89.263 +        String cls = m.group(1);
  89.264 +        return cls;
  89.265 +    }
  89.266 +
  89.267 +    String getHtml() {
  89.268 +        String fqn = "'" + pkg + '.' + cls + "'";
  89.269 +        return html.replace("'${fqn}'", fqn);
  89.270 +    }
  89.271 +
  89.272 +    void assertErrors() {
  89.273 +        assertFalse(getErrors().isEmpty(), "There are supposed to be some errors");
  89.274 +    }
  89.275 +
  89.276 +    void assertError(String expMsg) {
  89.277 +        StringBuilder sb = new StringBuilder();
  89.278 +        sb.append("Can't find ").append(expMsg).append(" among:");
  89.279 +        for (Diagnostic<? extends JavaFileObject> e : errors) {
  89.280 +            String msg = e.getMessage(Locale.US);
  89.281 +            if (msg.contains(expMsg)) {
  89.282 +                return;
  89.283 +            }
  89.284 +            sb.append("\n");
  89.285 +            sb.append(msg);
  89.286 +        }
  89.287 +        fail(sb.toString());
  89.288 +    }
  89.289 +}
    90.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    90.2 +++ b/geo/src/test/java/org/netbeans/html/geo/impl/GeoProcessorTest.java	Tue Jan 07 08:21:57 2014 +0100
    90.3 @@ -0,0 +1,114 @@
    90.4 +/**
    90.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    90.6 + *
    90.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
    90.8 + *
    90.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   90.10 + * Other names may be trademarks of their respective owners.
   90.11 + *
   90.12 + * The contents of this file are subject to the terms of either the GNU
   90.13 + * General Public License Version 2 only ("GPL") or the Common
   90.14 + * Development and Distribution License("CDDL") (collectively, the
   90.15 + * "License"). You may not use this file except in compliance with the
   90.16 + * License. You can obtain a copy of the License at
   90.17 + * http://www.netbeans.org/cddl-gplv2.html
   90.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   90.19 + * specific language governing permissions and limitations under the
   90.20 + * License.  When distributing the software, include this License Header
   90.21 + * Notice in each file and include the License file at
   90.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   90.23 + * particular file as subject to the "Classpath" exception as provided
   90.24 + * by Oracle in the GPL Version 2 section of the License file that
   90.25 + * accompanied this code. If applicable, add the following below the
   90.26 + * License Header, with the fields enclosed by brackets [] replaced by
   90.27 + * your own identifying information:
   90.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   90.29 + *
   90.30 + * Contributor(s):
   90.31 + *
   90.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   90.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   90.34 + *
   90.35 + * If you wish your version of this file to be governed by only the CDDL
   90.36 + * or only the GPL Version 2, indicate your decision by adding
   90.37 + * "[Contributor] elects to include this software in this distribution
   90.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   90.39 + * single choice of license, a recipient has the option to distribute
   90.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   90.41 + * to extend the choice of license to its licensees as provided above.
   90.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   90.43 + * Version 2 license, then the option applies only if the new code is
   90.44 + * made subject to such option by the copyright holder.
   90.45 + */
   90.46 +package org.netbeans.html.geo.impl;
   90.47 +
   90.48 +import java.io.IOException;
   90.49 +import org.testng.annotations.Test;
   90.50 +
   90.51 +/** Test whether the annotation processor detects errors correctly.
   90.52 + *
   90.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   90.54 + */
   90.55 +public class GeoProcessorTest {
   90.56 +    
   90.57 +    public GeoProcessorTest() {
   90.58 +    }
   90.59 +
   90.60 +    @Test public void onLocationMethodHasToTakePositionParameter() throws IOException {
   90.61 +        Compile res = Compile.create("", "package x;\n"
   90.62 +            + "class UseOnLocation {\n"
   90.63 +            + "  @net.java.html.geo.OnLocation\n"
   90.64 +            + "  public static void cantCallMe() {}\n"
   90.65 +            + "}\n"
   90.66 +        );
   90.67 +        res.assertErrors();
   90.68 +        res.assertError("first argument must be net.java.html.geo.Position");
   90.69 +    }
   90.70 +    
   90.71 +    @Test public void onLocationMethodCannotBePrivate() throws IOException {
   90.72 +        Compile res = Compile.create("", "package x;\n"
   90.73 +            + "class UseOnLocation {\n"
   90.74 +            + "  @net.java.html.geo.OnLocation\n"
   90.75 +            + "  private static void cantCallMe(net.java.html.geo.Position p) {}\n"
   90.76 +            + "}\n"
   90.77 +        );
   90.78 +        res.assertErrors();
   90.79 +        res.assertError("cannot be private");
   90.80 +    }
   90.81 +    
   90.82 +    @Test public void onErrorHasToExist() throws IOException {
   90.83 +        Compile res = Compile.create("", "package x;\n"
   90.84 +            + "class UseOnLocation {\n"
   90.85 +            + "  @net.java.html.geo.OnLocation(onError=\"doesNotExist\")\n"
   90.86 +            + "  static void cantCallMe(net.java.html.geo.Position p) {}\n"
   90.87 +            + "}\n"
   90.88 +        );
   90.89 +        res.assertErrors();
   90.90 +        res.assertError("not find doesNotExist");
   90.91 +    }
   90.92 +
   90.93 +    @Test public void onErrorWouldHaveToBeStatic() throws IOException {
   90.94 +        Compile res = Compile.create("", "package x;\n"
   90.95 +            + "class UseOnLocation {\n"
   90.96 +            + "  @net.java.html.geo.OnLocation(onError=\"notStatic\")\n"
   90.97 +            + "  static void cantCallMe(net.java.html.geo.Position p) {}\n"
   90.98 +            + "  void notStatic(Exception e) {}\n"
   90.99 +            + "}\n"
  90.100 +        );
  90.101 +        res.assertErrors();
  90.102 +        res.assertError("have to be static");
  90.103 +    }
  90.104 +
  90.105 +    @Test public void onErrorMustAcceptExceptionArgument() throws IOException {
  90.106 +        Compile res = Compile.create("", "package x;\n"
  90.107 +            + "class UseOnLocation {\n"
  90.108 +            + "  @net.java.html.geo.OnLocation(onError=\"notStatic\")\n"
  90.109 +            + "  static void cantCallMe(net.java.html.geo.Position p) {}\n"
  90.110 +            + "  static void notStatic(java.io.IOException e) {}\n"
  90.111 +            + "}\n"
  90.112 +        );
  90.113 +        res.assertErrors();
  90.114 +        res.assertError("Error method first argument needs to be Exception");
  90.115 +    }
  90.116 +    
  90.117 +}
    91.1 --- a/html4j-maven-plugin/src/main/java/org/apidesign/html/mojo/ProcessJsAnnotationsMojo.java	Thu Dec 19 17:11:01 2013 +0100
    91.2 +++ b/html4j-maven-plugin/src/main/java/org/apidesign/html/mojo/ProcessJsAnnotationsMojo.java	Tue Jan 07 08:21:57 2014 +0100
    91.3 @@ -1,22 +1,44 @@
    91.4  /**
    91.5 - * HTML via Java(tm) Language Bindings
    91.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    91.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    91.8   *
    91.9 - * This program is free software: you can redistribute it and/or modify
   91.10 - * it under the terms of the GNU General Public License as published by
   91.11 - * the Free Software Foundation, version 2 of the License.
   91.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   91.13   *
   91.14 - * This program is distributed in the hope that it will be useful,
   91.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   91.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   91.17 - * GNU General Public License for more details. apidesign.org
   91.18 - * designates this particular file as subject to the
   91.19 - * "Classpath" exception as provided by apidesign.org
   91.20 - * in the License file that accompanied this code.
   91.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   91.22 + * Other names may be trademarks of their respective owners.
   91.23   *
   91.24 - * You should have received a copy of the GNU General Public License
   91.25 - * along with this program. Look for COPYING file in the top folder.
   91.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   91.27 + * The contents of this file are subject to the terms of either the GNU
   91.28 + * General Public License Version 2 only ("GPL") or the Common
   91.29 + * Development and Distribution License("CDDL") (collectively, the
   91.30 + * "License"). You may not use this file except in compliance with the
   91.31 + * License. You can obtain a copy of the License at
   91.32 + * http://www.netbeans.org/cddl-gplv2.html
   91.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   91.34 + * specific language governing permissions and limitations under the
   91.35 + * License.  When distributing the software, include this License Header
   91.36 + * Notice in each file and include the License file at
   91.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   91.38 + * particular file as subject to the "Classpath" exception as provided
   91.39 + * by Oracle in the GPL Version 2 section of the License file that
   91.40 + * accompanied this code. If applicable, add the following below the
   91.41 + * License Header, with the fields enclosed by brackets [] replaced by
   91.42 + * your own identifying information:
   91.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   91.44 + *
   91.45 + * Contributor(s):
   91.46 + *
   91.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   91.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   91.49 + *
   91.50 + * If you wish your version of this file to be governed by only the CDDL
   91.51 + * or only the GPL Version 2, indicate your decision by adding
   91.52 + * "[Contributor] elects to include this software in this distribution
   91.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   91.54 + * single choice of license, a recipient has the option to distribute
   91.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   91.56 + * to extend the choice of license to its licensees as provided above.
   91.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   91.58 + * Version 2 license, then the option applies only if the new code is
   91.59 + * made subject to such option by the copyright holder.
   91.60   */
   91.61  package org.apidesign.html.mojo;
   91.62  
    92.1 --- a/html4j-maven-plugin/src/test/java/org/apidesign/html/mojo/GenerateBodyTest.java	Thu Dec 19 17:11:01 2013 +0100
    92.2 +++ b/html4j-maven-plugin/src/test/java/org/apidesign/html/mojo/GenerateBodyTest.java	Tue Jan 07 08:21:57 2014 +0100
    92.3 @@ -1,22 +1,44 @@
    92.4  /**
    92.5 - * HTML via Java(tm) Language Bindings
    92.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    92.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    92.8   *
    92.9 - * This program is free software: you can redistribute it and/or modify
   92.10 - * it under the terms of the GNU General Public License as published by
   92.11 - * the Free Software Foundation, version 2 of the License.
   92.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   92.13   *
   92.14 - * This program is distributed in the hope that it will be useful,
   92.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   92.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   92.17 - * GNU General Public License for more details. apidesign.org
   92.18 - * designates this particular file as subject to the
   92.19 - * "Classpath" exception as provided by apidesign.org
   92.20 - * in the License file that accompanied this code.
   92.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   92.22 + * Other names may be trademarks of their respective owners.
   92.23   *
   92.24 - * You should have received a copy of the GNU General Public License
   92.25 - * along with this program. Look for COPYING file in the top folder.
   92.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   92.27 + * The contents of this file are subject to the terms of either the GNU
   92.28 + * General Public License Version 2 only ("GPL") or the Common
   92.29 + * Development and Distribution License("CDDL") (collectively, the
   92.30 + * "License"). You may not use this file except in compliance with the
   92.31 + * License. You can obtain a copy of the License at
   92.32 + * http://www.netbeans.org/cddl-gplv2.html
   92.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   92.34 + * specific language governing permissions and limitations under the
   92.35 + * License.  When distributing the software, include this License Header
   92.36 + * Notice in each file and include the License file at
   92.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   92.38 + * particular file as subject to the "Classpath" exception as provided
   92.39 + * by Oracle in the GPL Version 2 section of the License file that
   92.40 + * accompanied this code. If applicable, add the following below the
   92.41 + * License Header, with the fields enclosed by brackets [] replaced by
   92.42 + * your own identifying information:
   92.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   92.44 + *
   92.45 + * Contributor(s):
   92.46 + *
   92.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   92.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   92.49 + *
   92.50 + * If you wish your version of this file to be governed by only the CDDL
   92.51 + * or only the GPL Version 2, indicate your decision by adding
   92.52 + * "[Contributor] elects to include this software in this distribution
   92.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   92.54 + * single choice of license, a recipient has the option to distribute
   92.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   92.56 + * to extend the choice of license to its licensees as provided above.
   92.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   92.58 + * Version 2 license, then the option applies only if the new code is
   92.59 + * made subject to such option by the copyright holder.
   92.60   */
   92.61  package org.apidesign.html.mojo;
   92.62  
    93.1 --- a/json-tck/pom.xml	Thu Dec 19 17:11:01 2013 +0100
    93.2 +++ b/json-tck/pom.xml	Tue Jan 07 08:21:57 2014 +0100
    93.3 @@ -2,11 +2,11 @@
    93.4  <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">
    93.5    <modelVersion>4.0.0</modelVersion>
    93.6    <parent>
    93.7 -    <groupId>org.apidesign</groupId>
    93.8 -    <artifactId>html</artifactId>
    93.9 +    <groupId>org.netbeans.html</groupId>
   93.10 +    <artifactId>pom</artifactId>
   93.11      <version>0.7-SNAPSHOT</version>
   93.12    </parent>
   93.13 -  <groupId>org.apidesign.html</groupId>
   93.14 +  <groupId>org.netbeans.html</groupId>
   93.15    <artifactId>net.java.html.json.tck</artifactId>
   93.16    <version>0.7-SNAPSHOT</version>
   93.17    <packaging>bundle</packaging>
   93.18 @@ -35,7 +35,7 @@
   93.19    </build>
   93.20    <dependencies>
   93.21      <dependency>
   93.22 -      <groupId>org.apidesign.html</groupId>
   93.23 +      <groupId>org.netbeans.html</groupId>
   93.24        <artifactId>net.java.html.json</artifactId>
   93.25        <version>0.7-SNAPSHOT</version>
   93.26        <type>jar</type>
    94.1 --- a/json-tck/src/main/java/net/java/html/js/tests/Bodies.java	Thu Dec 19 17:11:01 2013 +0100
    94.2 +++ b/json-tck/src/main/java/net/java/html/js/tests/Bodies.java	Tue Jan 07 08:21:57 2014 +0100
    94.3 @@ -1,24 +1,45 @@
    94.4  /**
    94.5 - * HTML via Java(tm) Language Bindings
    94.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    94.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    94.8   *
    94.9 - * This program is free software: you can redistribute it and/or modify
   94.10 - * it under the terms of the GNU General Public License as published by
   94.11 - * the Free Software Foundation, version 2 of the License.
   94.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   94.13   *
   94.14 - * This program is distributed in the hope that it will be useful,
   94.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   94.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   94.17 - * GNU General Public License for more details. apidesign.org
   94.18 - * designates this particular file as subject to the
   94.19 - * "Classpath" exception as provided by apidesign.org
   94.20 - * in the License file that accompanied this code.
   94.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   94.22 + * Other names may be trademarks of their respective owners.
   94.23   *
   94.24 - * You should have received a copy of the GNU General Public License
   94.25 - * along with this program. Look for COPYING file in the top folder.
   94.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   94.27 + * The contents of this file are subject to the terms of either the GNU
   94.28 + * General Public License Version 2 only ("GPL") or the Common
   94.29 + * Development and Distribution License("CDDL") (collectively, the
   94.30 + * "License"). You may not use this file except in compliance with the
   94.31 + * License. You can obtain a copy of the License at
   94.32 + * http://www.netbeans.org/cddl-gplv2.html
   94.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   94.34 + * specific language governing permissions and limitations under the
   94.35 + * License.  When distributing the software, include this License Header
   94.36 + * Notice in each file and include the License file at
   94.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   94.38 + * particular file as subject to the "Classpath" exception as provided
   94.39 + * by Oracle in the GPL Version 2 section of the License file that
   94.40 + * accompanied this code. If applicable, add the following below the
   94.41 + * License Header, with the fields enclosed by brackets [] replaced by
   94.42 + * your own identifying information:
   94.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   94.44 + *
   94.45 + * Contributor(s):
   94.46 + *
   94.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   94.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   94.49 + *
   94.50 + * If you wish your version of this file to be governed by only the CDDL
   94.51 + * or only the GPL Version 2, indicate your decision by adding
   94.52 + * "[Contributor] elects to include this software in this distribution
   94.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   94.54 + * single choice of license, a recipient has the option to distribute
   94.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   94.56 + * to extend the choice of license to its licensees as provided above.
   94.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   94.58 + * Version 2 license, then the option applies only if the new code is
   94.59 + * made subject to such option by the copyright holder.
   94.60   */
   94.61 -
   94.62  package net.java.html.js.tests;
   94.63  
   94.64  import java.util.concurrent.Callable;
    95.1 --- a/json-tck/src/main/java/net/java/html/js/tests/Factorial.java	Thu Dec 19 17:11:01 2013 +0100
    95.2 +++ b/json-tck/src/main/java/net/java/html/js/tests/Factorial.java	Tue Jan 07 08:21:57 2014 +0100
    95.3 @@ -1,23 +1,45 @@
    95.4  /**
    95.5 - * HTML via Java(tm) Language Bindings Copyright (C) 2013 Jaroslav Tulach
    95.6 - * <jaroslav.tulach@apidesign.org>
    95.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    95.8   *
    95.9 - * This program is free software: you can redistribute it and/or modify it under
   95.10 - * the terms of the GNU General Public License as published by the Free Software
   95.11 - * Foundation, version 2 of the License.
   95.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   95.13   *
   95.14 - * This program is distributed in the hope that it will be useful, but WITHOUT
   95.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   95.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
   95.17 - * details. apidesign.org designates this particular file as subject to the
   95.18 - * "Classpath" exception as provided by apidesign.org in the License file that
   95.19 - * accompanied this code.
   95.20 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   95.21 + * Other names may be trademarks of their respective owners.
   95.22   *
   95.23 - * You should have received a copy of the GNU General Public License along with
   95.24 - * this program. Look for COPYING file in the top folder. If not, see
   95.25 - * http://wiki.apidesign.org/wiki/GPLwithClassPathException
   95.26 + * The contents of this file are subject to the terms of either the GNU
   95.27 + * General Public License Version 2 only ("GPL") or the Common
   95.28 + * Development and Distribution License("CDDL") (collectively, the
   95.29 + * "License"). You may not use this file except in compliance with the
   95.30 + * License. You can obtain a copy of the License at
   95.31 + * http://www.netbeans.org/cddl-gplv2.html
   95.32 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   95.33 + * specific language governing permissions and limitations under the
   95.34 + * License.  When distributing the software, include this License Header
   95.35 + * Notice in each file and include the License file at
   95.36 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   95.37 + * particular file as subject to the "Classpath" exception as provided
   95.38 + * by Oracle in the GPL Version 2 section of the License file that
   95.39 + * accompanied this code. If applicable, add the following below the
   95.40 + * License Header, with the fields enclosed by brackets [] replaced by
   95.41 + * your own identifying information:
   95.42 + * "Portions Copyrighted [year] [name of copyright owner]"
   95.43 + *
   95.44 + * Contributor(s):
   95.45 + *
   95.46 + * The Original Software is NetBeans. The Initial Developer of the Original
   95.47 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   95.48 + *
   95.49 + * If you wish your version of this file to be governed by only the CDDL
   95.50 + * or only the GPL Version 2, indicate your decision by adding
   95.51 + * "[Contributor] elects to include this software in this distribution
   95.52 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   95.53 + * single choice of license, a recipient has the option to distribute
   95.54 + * your version of this file under either the CDDL, the GPL Version 2 or
   95.55 + * to extend the choice of license to its licensees as provided above.
   95.56 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   95.57 + * Version 2 license, then the option applies only if the new code is
   95.58 + * made subject to such option by the copyright holder.
   95.59   */
   95.60 -
   95.61  package net.java.html.js.tests;
   95.62  
   95.63  import net.java.html.js.JavaScriptBody;
    96.1 --- a/json-tck/src/main/java/net/java/html/js/tests/JavaScriptBodyTest.java	Thu Dec 19 17:11:01 2013 +0100
    96.2 +++ b/json-tck/src/main/java/net/java/html/js/tests/JavaScriptBodyTest.java	Tue Jan 07 08:21:57 2014 +0100
    96.3 @@ -1,22 +1,44 @@
    96.4  /**
    96.5 - * HTML via Java(tm) Language Bindings
    96.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    96.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    96.8   *
    96.9 - * This program is free software: you can redistribute it and/or modify
   96.10 - * it under the terms of the GNU General Public License as published by
   96.11 - * the Free Software Foundation, version 2 of the License.
   96.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   96.13   *
   96.14 - * This program is distributed in the hope that it will be useful,
   96.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   96.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   96.17 - * GNU General Public License for more details. apidesign.org
   96.18 - * designates this particular file as subject to the
   96.19 - * "Classpath" exception as provided by apidesign.org
   96.20 - * in the License file that accompanied this code.
   96.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   96.22 + * Other names may be trademarks of their respective owners.
   96.23   *
   96.24 - * You should have received a copy of the GNU General Public License
   96.25 - * along with this program. Look for COPYING file in the top folder.
   96.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   96.27 + * The contents of this file are subject to the terms of either the GNU
   96.28 + * General Public License Version 2 only ("GPL") or the Common
   96.29 + * Development and Distribution License("CDDL") (collectively, the
   96.30 + * "License"). You may not use this file except in compliance with the
   96.31 + * License. You can obtain a copy of the License at
   96.32 + * http://www.netbeans.org/cddl-gplv2.html
   96.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   96.34 + * specific language governing permissions and limitations under the
   96.35 + * License.  When distributing the software, include this License Header
   96.36 + * Notice in each file and include the License file at
   96.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   96.38 + * particular file as subject to the "Classpath" exception as provided
   96.39 + * by Oracle in the GPL Version 2 section of the License file that
   96.40 + * accompanied this code. If applicable, add the following below the
   96.41 + * License Header, with the fields enclosed by brackets [] replaced by
   96.42 + * your own identifying information:
   96.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   96.44 + *
   96.45 + * Contributor(s):
   96.46 + *
   96.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   96.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   96.49 + *
   96.50 + * If you wish your version of this file to be governed by only the CDDL
   96.51 + * or only the GPL Version 2, indicate your decision by adding
   96.52 + * "[Contributor] elects to include this software in this distribution
   96.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   96.54 + * single choice of license, a recipient has the option to distribute
   96.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   96.56 + * to extend the choice of license to its licensees as provided above.
   96.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   96.58 + * Version 2 license, then the option applies only if the new code is
   96.59 + * made subject to such option by the copyright holder.
   96.60   */
   96.61  package net.java.html.js.tests;
   96.62  
    97.1 --- a/json-tck/src/main/java/net/java/html/js/tests/Sum.java	Thu Dec 19 17:11:01 2013 +0100
    97.2 +++ b/json-tck/src/main/java/net/java/html/js/tests/Sum.java	Tue Jan 07 08:21:57 2014 +0100
    97.3 @@ -1,24 +1,45 @@
    97.4  /**
    97.5 - * HTML via Java(tm) Language Bindings
    97.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    97.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    97.8   *
    97.9 - * This program is free software: you can redistribute it and/or modify
   97.10 - * it under the terms of the GNU General Public License as published by
   97.11 - * the Free Software Foundation, version 2 of the License.
   97.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   97.13   *
   97.14 - * This program is distributed in the hope that it will be useful,
   97.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   97.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   97.17 - * GNU General Public License for more details. apidesign.org
   97.18 - * designates this particular file as subject to the
   97.19 - * "Classpath" exception as provided by apidesign.org
   97.20 - * in the License file that accompanied this code.
   97.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   97.22 + * Other names may be trademarks of their respective owners.
   97.23   *
   97.24 - * You should have received a copy of the GNU General Public License
   97.25 - * along with this program. Look for COPYING file in the top folder.
   97.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   97.27 + * The contents of this file are subject to the terms of either the GNU
   97.28 + * General Public License Version 2 only ("GPL") or the Common
   97.29 + * Development and Distribution License("CDDL") (collectively, the
   97.30 + * "License"). You may not use this file except in compliance with the
   97.31 + * License. You can obtain a copy of the License at
   97.32 + * http://www.netbeans.org/cddl-gplv2.html
   97.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   97.34 + * specific language governing permissions and limitations under the
   97.35 + * License.  When distributing the software, include this License Header
   97.36 + * Notice in each file and include the License file at
   97.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   97.38 + * particular file as subject to the "Classpath" exception as provided
   97.39 + * by Oracle in the GPL Version 2 section of the License file that
   97.40 + * accompanied this code. If applicable, add the following below the
   97.41 + * License Header, with the fields enclosed by brackets [] replaced by
   97.42 + * your own identifying information:
   97.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   97.44 + *
   97.45 + * Contributor(s):
   97.46 + *
   97.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   97.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   97.49 + *
   97.50 + * If you wish your version of this file to be governed by only the CDDL
   97.51 + * or only the GPL Version 2, indicate your decision by adding
   97.52 + * "[Contributor] elects to include this software in this distribution
   97.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   97.54 + * single choice of license, a recipient has the option to distribute
   97.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   97.56 + * to extend the choice of license to its licensees as provided above.
   97.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   97.58 + * Version 2 license, then the option applies only if the new code is
   97.59 + * made subject to such option by the copyright holder.
   97.60   */
   97.61 -
   97.62  package net.java.html.js.tests;
   97.63  
   97.64  /**
    98.1 --- a/json-tck/src/main/java/net/java/html/json/tests/ConvertTypesTest.java	Thu Dec 19 17:11:01 2013 +0100
    98.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/ConvertTypesTest.java	Tue Jan 07 08:21:57 2014 +0100
    98.3 @@ -1,22 +1,44 @@
    98.4  /**
    98.5 - * HTML via Java(tm) Language Bindings
    98.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    98.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    98.8   *
    98.9 - * This program is free software: you can redistribute it and/or modify
   98.10 - * it under the terms of the GNU General Public License as published by
   98.11 - * the Free Software Foundation, version 2 of the License.
   98.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   98.13   *
   98.14 - * This program is distributed in the hope that it will be useful,
   98.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   98.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   98.17 - * GNU General Public License for more details. apidesign.org
   98.18 - * designates this particular file as subject to the
   98.19 - * "Classpath" exception as provided by apidesign.org
   98.20 - * in the License file that accompanied this code.
   98.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   98.22 + * Other names may be trademarks of their respective owners.
   98.23   *
   98.24 - * You should have received a copy of the GNU General Public License
   98.25 - * along with this program. Look for COPYING file in the top folder.
   98.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   98.27 + * The contents of this file are subject to the terms of either the GNU
   98.28 + * General Public License Version 2 only ("GPL") or the Common
   98.29 + * Development and Distribution License("CDDL") (collectively, the
   98.30 + * "License"). You may not use this file except in compliance with the
   98.31 + * License. You can obtain a copy of the License at
   98.32 + * http://www.netbeans.org/cddl-gplv2.html
   98.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   98.34 + * specific language governing permissions and limitations under the
   98.35 + * License.  When distributing the software, include this License Header
   98.36 + * Notice in each file and include the License file at
   98.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   98.38 + * particular file as subject to the "Classpath" exception as provided
   98.39 + * by Oracle in the GPL Version 2 section of the License file that
   98.40 + * accompanied this code. If applicable, add the following below the
   98.41 + * License Header, with the fields enclosed by brackets [] replaced by
   98.42 + * your own identifying information:
   98.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   98.44 + *
   98.45 + * Contributor(s):
   98.46 + *
   98.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   98.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   98.49 + *
   98.50 + * If you wish your version of this file to be governed by only the CDDL
   98.51 + * or only the GPL Version 2, indicate your decision by adding
   98.52 + * "[Contributor] elects to include this software in this distribution
   98.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   98.54 + * single choice of license, a recipient has the option to distribute
   98.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   98.56 + * to extend the choice of license to its licensees as provided above.
   98.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   98.58 + * Version 2 license, then the option applies only if the new code is
   98.59 + * made subject to such option by the copyright holder.
   98.60   */
   98.61  package net.java.html.json.tests;
   98.62  
   98.63 @@ -27,7 +49,6 @@
   98.64  import java.util.Map;
   98.65  import net.java.html.BrwsrCtx;
   98.66  import net.java.html.json.Models;
   98.67 -import org.apidesign.html.json.impl.JSON;
   98.68  import org.apidesign.html.json.tck.KOTest;
   98.69  
   98.70  /**
   98.71 @@ -64,7 +85,7 @@
   98.72      public void testConvertToPeople() throws Exception {
   98.73          final Object o = createJSON(true);
   98.74          
   98.75 -        Person p = JSON.read(newContext(), Person.class, o);
   98.76 +        Person p = Models.fromRaw(newContext(), Person.class, o);
   98.77          
   98.78          assert "son".equals(p.getFirstName()) : "First name: " + p.getFirstName();
   98.79          assert "dj".equals(p.getLastName()) : "Last name: " + p.getLastName();
   98.80 @@ -101,7 +122,7 @@
   98.81      public void testConvertToPeopleWithoutSex() throws Exception {
   98.82          final Object o = createJSON(false);
   98.83          
   98.84 -        Person p = JSON.read(newContext(), Person.class, o);
   98.85 +        Person p = Models.fromRaw(newContext(), Person.class, o);
   98.86          
   98.87          assert "son".equals(p.getFirstName()) : "First name: " + p.getFirstName();
   98.88          assert "dj".equals(p.getLastName()) : "Last name: " + p.getLastName();
    99.1 --- a/json-tck/src/main/java/net/java/html/json/tests/JSONTest.java	Thu Dec 19 17:11:01 2013 +0100
    99.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/JSONTest.java	Tue Jan 07 08:21:57 2014 +0100
    99.3 @@ -1,22 +1,44 @@
    99.4  /**
    99.5 - * HTML via Java(tm) Language Bindings
    99.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    99.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    99.8   *
    99.9 - * This program is free software: you can redistribute it and/or modify
   99.10 - * it under the terms of the GNU General Public License as published by
   99.11 - * the Free Software Foundation, version 2 of the License.
   99.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   99.13   *
   99.14 - * This program is distributed in the hope that it will be useful,
   99.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   99.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   99.17 - * GNU General Public License for more details. apidesign.org
   99.18 - * designates this particular file as subject to the
   99.19 - * "Classpath" exception as provided by apidesign.org
   99.20 - * in the License file that accompanied this code.
   99.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   99.22 + * Other names may be trademarks of their respective owners.
   99.23   *
   99.24 - * You should have received a copy of the GNU General Public License
   99.25 - * along with this program. Look for COPYING file in the top folder.
   99.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   99.27 + * The contents of this file are subject to the terms of either the GNU
   99.28 + * General Public License Version 2 only ("GPL") or the Common
   99.29 + * Development and Distribution License("CDDL") (collectively, the
   99.30 + * "License"). You may not use this file except in compliance with the
   99.31 + * License. You can obtain a copy of the License at
   99.32 + * http://www.netbeans.org/cddl-gplv2.html
   99.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   99.34 + * specific language governing permissions and limitations under the
   99.35 + * License.  When distributing the software, include this License Header
   99.36 + * Notice in each file and include the License file at
   99.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   99.38 + * particular file as subject to the "Classpath" exception as provided
   99.39 + * by Oracle in the GPL Version 2 section of the License file that
   99.40 + * accompanied this code. If applicable, add the following below the
   99.41 + * License Header, with the fields enclosed by brackets [] replaced by
   99.42 + * your own identifying information:
   99.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   99.44 + *
   99.45 + * Contributor(s):
   99.46 + *
   99.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   99.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   99.49 + *
   99.50 + * If you wish your version of this file to be governed by only the CDDL
   99.51 + * or only the GPL Version 2, indicate your decision by adding
   99.52 + * "[Contributor] elects to include this software in this distribution
   99.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   99.54 + * single choice of license, a recipient has the option to distribute
   99.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   99.56 + * to extend the choice of license to its licensees as provided above.
   99.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   99.58 + * Version 2 license, then the option applies only if the new code is
   99.59 + * made subject to such option by the copyright holder.
   99.60   */
   99.61  package net.java.html.json.tests;
   99.62  
   99.63 @@ -27,7 +49,6 @@
   99.64  import net.java.html.json.Models;
   99.65  import net.java.html.json.OnReceive;
   99.66  import net.java.html.json.Property;
   99.67 -import org.apidesign.html.json.impl.JSON;
   99.68  import org.apidesign.html.json.tck.KOTest;
   99.69  
   99.70  /** Need to verify that models produce reasonable JSON objects.
   99.71 @@ -62,7 +83,7 @@
   99.72              throw new IllegalStateException("Can't parse " + p).initCause(ex);
   99.73          }
   99.74          
   99.75 -        Person p2 = JSON.read(newContext(), Person.class, json);
   99.76 +        Person p2 = Models.fromRaw(newContext(), Person.class, json);
   99.77          
   99.78          assert p2.getFirstName().equals(p.getFirstName()) : 
   99.79              "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
   99.80 @@ -82,7 +103,7 @@
   99.81              throw new IllegalStateException("Can't parse " + txt).initCause(ex);
   99.82          }
   99.83          
   99.84 -        Person p2 = JSON.read(newContext(), Person.class, json);
   99.85 +        Person p2 = Models.fromRaw(newContext(), Person.class, json);
   99.86          
   99.87          assert p2.getFirstName().equals(p.getFirstName()) : 
   99.88              "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
   99.89 @@ -102,7 +123,7 @@
   99.90              throw new IllegalStateException("Can't parse " + txt).initCause(ex);
   99.91          }
   99.92          
   99.93 -        Person p2 = JSON.read(newContext(), Person.class, json);
   99.94 +        Person p2 = Models.fromRaw(newContext(), Person.class, json);
   99.95          
   99.96          assert p2.getFirstName().equals(p.getFirstName()) : 
   99.97              "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
   99.98 @@ -122,7 +143,7 @@
   99.99              throw new IllegalStateException("Can't parse " + txt).initCause(ex);
  99.100          }
  99.101          
  99.102 -        Person p2 = JSON.read(newContext(), Person.class, json);
  99.103 +        Person p2 = Models.fromRaw(newContext(), Person.class, json);
  99.104          
  99.105          assert p2.getFirstName().equals(p.getFirstName()) : 
  99.106              "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
   100.1 --- a/json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java	Thu Dec 19 17:11:01 2013 +0100
   100.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java	Tue Jan 07 08:21:57 2014 +0100
   100.3 @@ -1,22 +1,44 @@
   100.4  /**
   100.5 - * HTML via Java(tm) Language Bindings
   100.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   100.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   100.8   *
   100.9 - * This program is free software: you can redistribute it and/or modify
  100.10 - * it under the terms of the GNU General Public License as published by
  100.11 - * the Free Software Foundation, version 2 of the License.
  100.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  100.13   *
  100.14 - * This program is distributed in the hope that it will be useful,
  100.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  100.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  100.17 - * GNU General Public License for more details. apidesign.org
  100.18 - * designates this particular file as subject to the
  100.19 - * "Classpath" exception as provided by apidesign.org
  100.20 - * in the License file that accompanied this code.
  100.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  100.22 + * Other names may be trademarks of their respective owners.
  100.23   *
  100.24 - * You should have received a copy of the GNU General Public License
  100.25 - * along with this program. Look for COPYING file in the top folder.
  100.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  100.27 + * The contents of this file are subject to the terms of either the GNU
  100.28 + * General Public License Version 2 only ("GPL") or the Common
  100.29 + * Development and Distribution License("CDDL") (collectively, the
  100.30 + * "License"). You may not use this file except in compliance with the
  100.31 + * License. You can obtain a copy of the License at
  100.32 + * http://www.netbeans.org/cddl-gplv2.html
  100.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  100.34 + * specific language governing permissions and limitations under the
  100.35 + * License.  When distributing the software, include this License Header
  100.36 + * Notice in each file and include the License file at
  100.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  100.38 + * particular file as subject to the "Classpath" exception as provided
  100.39 + * by Oracle in the GPL Version 2 section of the License file that
  100.40 + * accompanied this code. If applicable, add the following below the
  100.41 + * License Header, with the fields enclosed by brackets [] replaced by
  100.42 + * your own identifying information:
  100.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  100.44 + *
  100.45 + * Contributor(s):
  100.46 + *
  100.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  100.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  100.49 + *
  100.50 + * If you wish your version of this file to be governed by only the CDDL
  100.51 + * or only the GPL Version 2, indicate your decision by adding
  100.52 + * "[Contributor] elects to include this software in this distribution
  100.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  100.54 + * single choice of license, a recipient has the option to distribute
  100.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  100.56 + * to extend the choice of license to its licensees as provided above.
  100.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  100.58 + * Version 2 license, then the option applies only if the new code is
  100.59 + * made subject to such option by the copyright holder.
  100.60   */
  100.61  package net.java.html.json.tests;
  100.62  
  100.63 @@ -28,6 +50,7 @@
  100.64  import net.java.html.json.Models;
  100.65  import net.java.html.json.Property;
  100.66  import org.apidesign.html.json.tck.KOTest;
  100.67 +import org.apidesign.html.json.tck.KnockoutTCK;
  100.68  
  100.69  /**
  100.70   *
   101.1 --- a/json-tck/src/main/java/net/java/html/json/tests/OperationsTest.java	Thu Dec 19 17:11:01 2013 +0100
   101.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/OperationsTest.java	Tue Jan 07 08:21:57 2014 +0100
   101.3 @@ -1,22 +1,44 @@
   101.4  /**
   101.5 - * HTML via Java(tm) Language Bindings
   101.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   101.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   101.8   *
   101.9 - * This program is free software: you can redistribute it and/or modify
  101.10 - * it under the terms of the GNU General Public License as published by
  101.11 - * the Free Software Foundation, version 2 of the License.
  101.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  101.13   *
  101.14 - * This program is distributed in the hope that it will be useful,
  101.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  101.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  101.17 - * GNU General Public License for more details. apidesign.org
  101.18 - * designates this particular file as subject to the
  101.19 - * "Classpath" exception as provided by apidesign.org
  101.20 - * in the License file that accompanied this code.
  101.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  101.22 + * Other names may be trademarks of their respective owners.
  101.23   *
  101.24 - * You should have received a copy of the GNU General Public License
  101.25 - * along with this program. Look for COPYING file in the top folder.
  101.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  101.27 + * The contents of this file are subject to the terms of either the GNU
  101.28 + * General Public License Version 2 only ("GPL") or the Common
  101.29 + * Development and Distribution License("CDDL") (collectively, the
  101.30 + * "License"). You may not use this file except in compliance with the
  101.31 + * License. You can obtain a copy of the License at
  101.32 + * http://www.netbeans.org/cddl-gplv2.html
  101.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  101.34 + * specific language governing permissions and limitations under the
  101.35 + * License.  When distributing the software, include this License Header
  101.36 + * Notice in each file and include the License file at
  101.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  101.38 + * particular file as subject to the "Classpath" exception as provided
  101.39 + * by Oracle in the GPL Version 2 section of the License file that
  101.40 + * accompanied this code. If applicable, add the following below the
  101.41 + * License Header, with the fields enclosed by brackets [] replaced by
  101.42 + * your own identifying information:
  101.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  101.44 + *
  101.45 + * Contributor(s):
  101.46 + *
  101.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  101.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  101.49 + *
  101.50 + * If you wish your version of this file to be governed by only the CDDL
  101.51 + * or only the GPL Version 2, indicate your decision by adding
  101.52 + * "[Contributor] elects to include this software in this distribution
  101.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  101.54 + * single choice of license, a recipient has the option to distribute
  101.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  101.56 + * to extend the choice of license to its licensees as provided above.
  101.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  101.58 + * Version 2 license, then the option applies only if the new code is
  101.59 + * made subject to such option by the copyright holder.
  101.60   */
  101.61  package net.java.html.json.tests;
  101.62  
   102.1 --- a/json-tck/src/main/java/net/java/html/json/tests/PairModel.java	Thu Dec 19 17:11:01 2013 +0100
   102.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/PairModel.java	Tue Jan 07 08:21:57 2014 +0100
   102.3 @@ -1,22 +1,44 @@
   102.4  /**
   102.5 - * HTML via Java(tm) Language Bindings
   102.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   102.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   102.8   *
   102.9 - * This program is free software: you can redistribute it and/or modify
  102.10 - * it under the terms of the GNU General Public License as published by
  102.11 - * the Free Software Foundation, version 2 of the License.
  102.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  102.13   *
  102.14 - * This program is distributed in the hope that it will be useful,
  102.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  102.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  102.17 - * GNU General Public License for more details. apidesign.org
  102.18 - * designates this particular file as subject to the
  102.19 - * "Classpath" exception as provided by apidesign.org
  102.20 - * in the License file that accompanied this code.
  102.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  102.22 + * Other names may be trademarks of their respective owners.
  102.23   *
  102.24 - * You should have received a copy of the GNU General Public License
  102.25 - * along with this program. Look for COPYING file in the top folder.
  102.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  102.27 + * The contents of this file are subject to the terms of either the GNU
  102.28 + * General Public License Version 2 only ("GPL") or the Common
  102.29 + * Development and Distribution License("CDDL") (collectively, the
  102.30 + * "License"). You may not use this file except in compliance with the
  102.31 + * License. You can obtain a copy of the License at
  102.32 + * http://www.netbeans.org/cddl-gplv2.html
  102.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  102.34 + * specific language governing permissions and limitations under the
  102.35 + * License.  When distributing the software, include this License Header
  102.36 + * Notice in each file and include the License file at
  102.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  102.38 + * particular file as subject to the "Classpath" exception as provided
  102.39 + * by Oracle in the GPL Version 2 section of the License file that
  102.40 + * accompanied this code. If applicable, add the following below the
  102.41 + * License Header, with the fields enclosed by brackets [] replaced by
  102.42 + * your own identifying information:
  102.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  102.44 + *
  102.45 + * Contributor(s):
  102.46 + *
  102.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  102.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  102.49 + *
  102.50 + * If you wish your version of this file to be governed by only the CDDL
  102.51 + * or only the GPL Version 2, indicate your decision by adding
  102.52 + * "[Contributor] elects to include this software in this distribution
  102.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  102.54 + * single choice of license, a recipient has the option to distribute
  102.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  102.56 + * to extend the choice of license to its licensees as provided above.
  102.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  102.58 + * Version 2 license, then the option applies only if the new code is
  102.59 + * made subject to such option by the copyright holder.
  102.60   */
  102.61  package net.java.html.json.tests;
  102.62  
   103.1 --- a/json-tck/src/main/java/net/java/html/json/tests/PersonImpl.java	Thu Dec 19 17:11:01 2013 +0100
   103.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/PersonImpl.java	Tue Jan 07 08:21:57 2014 +0100
   103.3 @@ -1,22 +1,44 @@
   103.4  /**
   103.5 - * HTML via Java(tm) Language Bindings
   103.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   103.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   103.8   *
   103.9 - * This program is free software: you can redistribute it and/or modify
  103.10 - * it under the terms of the GNU General Public License as published by
  103.11 - * the Free Software Foundation, version 2 of the License.
  103.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  103.13   *
  103.14 - * This program is distributed in the hope that it will be useful,
  103.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  103.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  103.17 - * GNU General Public License for more details. apidesign.org
  103.18 - * designates this particular file as subject to the
  103.19 - * "Classpath" exception as provided by apidesign.org
  103.20 - * in the License file that accompanied this code.
  103.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  103.22 + * Other names may be trademarks of their respective owners.
  103.23   *
  103.24 - * You should have received a copy of the GNU General Public License
  103.25 - * along with this program. Look for COPYING file in the top folder.
  103.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  103.27 + * The contents of this file are subject to the terms of either the GNU
  103.28 + * General Public License Version 2 only ("GPL") or the Common
  103.29 + * Development and Distribution License("CDDL") (collectively, the
  103.30 + * "License"). You may not use this file except in compliance with the
  103.31 + * License. You can obtain a copy of the License at
  103.32 + * http://www.netbeans.org/cddl-gplv2.html
  103.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  103.34 + * specific language governing permissions and limitations under the
  103.35 + * License.  When distributing the software, include this License Header
  103.36 + * Notice in each file and include the License file at
  103.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  103.38 + * particular file as subject to the "Classpath" exception as provided
  103.39 + * by Oracle in the GPL Version 2 section of the License file that
  103.40 + * accompanied this code. If applicable, add the following below the
  103.41 + * License Header, with the fields enclosed by brackets [] replaced by
  103.42 + * your own identifying information:
  103.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  103.44 + *
  103.45 + * Contributor(s):
  103.46 + *
  103.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  103.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  103.49 + *
  103.50 + * If you wish your version of this file to be governed by only the CDDL
  103.51 + * or only the GPL Version 2, indicate your decision by adding
  103.52 + * "[Contributor] elects to include this software in this distribution
  103.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  103.54 + * single choice of license, a recipient has the option to distribute
  103.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  103.56 + * to extend the choice of license to its licensees as provided above.
  103.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  103.58 + * Version 2 license, then the option applies only if the new code is
  103.59 + * made subject to such option by the copyright holder.
  103.60   */
  103.61  package net.java.html.json.tests;
  103.62  
   104.1 --- a/json-tck/src/main/java/net/java/html/json/tests/Sex.java	Thu Dec 19 17:11:01 2013 +0100
   104.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/Sex.java	Tue Jan 07 08:21:57 2014 +0100
   104.3 @@ -1,22 +1,44 @@
   104.4  /**
   104.5 - * HTML via Java(tm) Language Bindings
   104.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   104.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   104.8   *
   104.9 - * This program is free software: you can redistribute it and/or modify
  104.10 - * it under the terms of the GNU General Public License as published by
  104.11 - * the Free Software Foundation, version 2 of the License.
  104.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  104.13   *
  104.14 - * This program is distributed in the hope that it will be useful,
  104.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  104.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  104.17 - * GNU General Public License for more details. apidesign.org
  104.18 - * designates this particular file as subject to the
  104.19 - * "Classpath" exception as provided by apidesign.org
  104.20 - * in the License file that accompanied this code.
  104.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  104.22 + * Other names may be trademarks of their respective owners.
  104.23   *
  104.24 - * You should have received a copy of the GNU General Public License
  104.25 - * along with this program. Look for COPYING file in the top folder.
  104.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  104.27 + * The contents of this file are subject to the terms of either the GNU
  104.28 + * General Public License Version 2 only ("GPL") or the Common
  104.29 + * Development and Distribution License("CDDL") (collectively, the
  104.30 + * "License"). You may not use this file except in compliance with the
  104.31 + * License. You can obtain a copy of the License at
  104.32 + * http://www.netbeans.org/cddl-gplv2.html
  104.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  104.34 + * specific language governing permissions and limitations under the
  104.35 + * License.  When distributing the software, include this License Header
  104.36 + * Notice in each file and include the License file at
  104.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  104.38 + * particular file as subject to the "Classpath" exception as provided
  104.39 + * by Oracle in the GPL Version 2 section of the License file that
  104.40 + * accompanied this code. If applicable, add the following below the
  104.41 + * License Header, with the fields enclosed by brackets [] replaced by
  104.42 + * your own identifying information:
  104.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  104.44 + *
  104.45 + * Contributor(s):
  104.46 + *
  104.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  104.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  104.49 + *
  104.50 + * If you wish your version of this file to be governed by only the CDDL
  104.51 + * or only the GPL Version 2, indicate your decision by adding
  104.52 + * "[Contributor] elects to include this software in this distribution
  104.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  104.54 + * single choice of license, a recipient has the option to distribute
  104.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  104.56 + * to extend the choice of license to its licensees as provided above.
  104.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  104.58 + * Version 2 license, then the option applies only if the new code is
  104.59 + * made subject to such option by the copyright holder.
  104.60   */
  104.61  package net.java.html.json.tests;
  104.62  
   105.1 --- a/json-tck/src/main/java/net/java/html/json/tests/Utils.java	Thu Dec 19 17:11:01 2013 +0100
   105.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/Utils.java	Tue Jan 07 08:21:57 2014 +0100
   105.3 @@ -1,26 +1,49 @@
   105.4  /**
   105.5 - * HTML via Java(tm) Language Bindings
   105.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   105.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   105.8   *
   105.9 - * This program is free software: you can redistribute it and/or modify
  105.10 - * it under the terms of the GNU General Public License as published by
  105.11 - * the Free Software Foundation, version 2 of the License.
  105.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  105.13   *
  105.14 - * This program is distributed in the hope that it will be useful,
  105.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  105.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  105.17 - * GNU General Public License for more details. apidesign.org
  105.18 - * designates this particular file as subject to the
  105.19 - * "Classpath" exception as provided by apidesign.org
  105.20 - * in the License file that accompanied this code.
  105.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  105.22 + * Other names may be trademarks of their respective owners.
  105.23   *
  105.24 - * You should have received a copy of the GNU General Public License
  105.25 - * along with this program. Look for COPYING file in the top folder.
  105.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  105.27 + * The contents of this file are subject to the terms of either the GNU
  105.28 + * General Public License Version 2 only ("GPL") or the Common
  105.29 + * Development and Distribution License("CDDL") (collectively, the
  105.30 + * "License"). You may not use this file except in compliance with the
  105.31 + * License. You can obtain a copy of the License at
  105.32 + * http://www.netbeans.org/cddl-gplv2.html
  105.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  105.34 + * specific language governing permissions and limitations under the
  105.35 + * License.  When distributing the software, include this License Header
  105.36 + * Notice in each file and include the License file at
  105.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  105.38 + * particular file as subject to the "Classpath" exception as provided
  105.39 + * by Oracle in the GPL Version 2 section of the License file that
  105.40 + * accompanied this code. If applicable, add the following below the
  105.41 + * License Header, with the fields enclosed by brackets [] replaced by
  105.42 + * your own identifying information:
  105.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  105.44 + *
  105.45 + * Contributor(s):
  105.46 + *
  105.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  105.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  105.49 + *
  105.50 + * If you wish your version of this file to be governed by only the CDDL
  105.51 + * or only the GPL Version 2, indicate your decision by adding
  105.52 + * "[Contributor] elects to include this software in this distribution
  105.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  105.54 + * single choice of license, a recipient has the option to distribute
  105.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  105.56 + * to extend the choice of license to its licensees as provided above.
  105.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  105.58 + * Version 2 license, then the option applies only if the new code is
  105.59 + * made subject to such option by the copyright holder.
  105.60   */
  105.61  package net.java.html.json.tests;
  105.62  
  105.63  import java.net.URI;
  105.64 +import java.util.Collections;
  105.65  import java.util.Map;
  105.66  import java.util.ServiceLoader;
  105.67  import net.java.html.BrwsrCtx;
  105.68 @@ -30,12 +53,18 @@
  105.69   *
  105.70   * @author Jaroslav Tulach <jtulach@netbeans.org>
  105.71   */
  105.72 -final class Utils {
  105.73 +public final class Utils {
  105.74 +    private static KnockoutTCK instantiatedTCK;
  105.75 +    
  105.76      private Utils() {
  105.77      }
  105.78 +    
  105.79 +    public static void registerTCK(KnockoutTCK tck) {
  105.80 +        instantiatedTCK = tck;
  105.81 +    }
  105.82  
  105.83      static  BrwsrCtx newContext(Class<?> clazz) {
  105.84 -        for (KnockoutTCK tck : ServiceLoader.load(KnockoutTCK.class, cl(clazz))) {
  105.85 +        for (KnockoutTCK tck : tcks(clazz)) {
  105.86              BrwsrCtx c = tck.createContext();
  105.87              if (c != null) {
  105.88                  return c;
  105.89 @@ -44,7 +73,7 @@
  105.90          throw new AssertionError("Can't find appropriate Context in ServiceLoader!");
  105.91      }
  105.92      static Object createObject(Map<String,Object> values, Class<?> clazz) {
  105.93 -        for (KnockoutTCK tck : ServiceLoader.load(KnockoutTCK.class, cl(clazz))) {
  105.94 +        for (KnockoutTCK tck : tcks(clazz)) {
  105.95              Object o = tck.createJSON(values);
  105.96              if (o != null) {
  105.97                  return o;
  105.98 @@ -55,11 +84,18 @@
  105.99      static Object executeScript(Class<?> clazz, 
 105.100          String script, Object... arguments
 105.101      ) throws Exception {
 105.102 -        for (KnockoutTCK tck : ServiceLoader.load(KnockoutTCK.class, cl(clazz))) {
 105.103 +        for (KnockoutTCK tck : tcks(clazz)) {
 105.104              return tck.executeScript(script, arguments);
 105.105          }
 105.106          throw new AssertionError("Can't find appropriate Context in ServiceLoader!");
 105.107      }
 105.108 +
 105.109 +    private static Iterable<KnockoutTCK> tcks(Class<?> clazz) {
 105.110 +        if (instantiatedTCK != null) {
 105.111 +            return Collections.singleton(instantiatedTCK);
 105.112 +        }
 105.113 +        return ServiceLoader.load(KnockoutTCK.class, cl(clazz));
 105.114 +    }
 105.115      
 105.116      static Object exposeHTML(Class<?> clazz, String html) throws Exception {
 105.117          String s = 
 105.118 @@ -76,7 +112,7 @@
 105.119  
 105.120      static String prepareURL(
 105.121          Class<?> clazz, String content, String mimeType, String... parameters) {
 105.122 -        for (KnockoutTCK tck : ServiceLoader.load(KnockoutTCK.class, cl(clazz))) {
 105.123 +        for (KnockoutTCK tck : tcks(clazz)) {
 105.124              URI o = tck.prepareURL(content, mimeType, parameters);
 105.125              if (o != null) {
 105.126                  return o.toString();
 105.127 @@ -87,7 +123,7 @@
 105.128  
 105.129      static boolean canFailWebSockets(
 105.130          Class<?> clazz) {
 105.131 -        for (KnockoutTCK tck : ServiceLoader.load(KnockoutTCK.class, cl(clazz))) {
 105.132 +        for (KnockoutTCK tck : tcks(clazz)) {
 105.133              if (tck.canFailWebSocketTest()) {
 105.134                  return true;
 105.135              }
   106.1 --- a/json-tck/src/main/java/net/java/html/json/tests/WebSocketTest.java	Thu Dec 19 17:11:01 2013 +0100
   106.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/WebSocketTest.java	Tue Jan 07 08:21:57 2014 +0100
   106.3 @@ -1,22 +1,44 @@
   106.4  /**
   106.5 - * HTML via Java(tm) Language Bindings
   106.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   106.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   106.8   *
   106.9 - * This program is free software: you can redistribute it and/or modify
  106.10 - * it under the terms of the GNU General Public License as published by
  106.11 - * the Free Software Foundation, version 2 of the License.
  106.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  106.13   *
  106.14 - * This program is distributed in the hope that it will be useful,
  106.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  106.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  106.17 - * GNU General Public License for more details. apidesign.org
  106.18 - * designates this particular file as subject to the
  106.19 - * "Classpath" exception as provided by apidesign.org
  106.20 - * in the License file that accompanied this code.
  106.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  106.22 + * Other names may be trademarks of their respective owners.
  106.23   *
  106.24 - * You should have received a copy of the GNU General Public License
  106.25 - * along with this program. Look for COPYING file in the top folder.
  106.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  106.27 + * The contents of this file are subject to the terms of either the GNU
  106.28 + * General Public License Version 2 only ("GPL") or the Common
  106.29 + * Development and Distribution License("CDDL") (collectively, the
  106.30 + * "License"). You may not use this file except in compliance with the
  106.31 + * License. You can obtain a copy of the License at
  106.32 + * http://www.netbeans.org/cddl-gplv2.html
  106.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  106.34 + * specific language governing permissions and limitations under the
  106.35 + * License.  When distributing the software, include this License Header
  106.36 + * Notice in each file and include the License file at
  106.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  106.38 + * particular file as subject to the "Classpath" exception as provided
  106.39 + * by Oracle in the GPL Version 2 section of the License file that
  106.40 + * accompanied this code. If applicable, add the following below the
  106.41 + * License Header, with the fields enclosed by brackets [] replaced by
  106.42 + * your own identifying information:
  106.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  106.44 + *
  106.45 + * Contributor(s):
  106.46 + *
  106.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  106.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  106.49 + *
  106.50 + * If you wish your version of this file to be governed by only the CDDL
  106.51 + * or only the GPL Version 2, indicate your decision by adding
  106.52 + * "[Contributor] elects to include this software in this distribution
  106.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  106.54 + * single choice of license, a recipient has the option to distribute
  106.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  106.56 + * to extend the choice of license to its licensees as provided above.
  106.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  106.58 + * Version 2 license, then the option applies only if the new code is
  106.59 + * made subject to such option by the copyright holder.
  106.60   */
  106.61  package net.java.html.json.tests;
  106.62  
   107.1 --- a/json-tck/src/main/java/org/apidesign/html/json/tck/JavaScriptTCK.java	Thu Dec 19 17:11:01 2013 +0100
   107.2 +++ b/json-tck/src/main/java/org/apidesign/html/json/tck/JavaScriptTCK.java	Tue Jan 07 08:21:57 2014 +0100
   107.3 @@ -1,22 +1,44 @@
   107.4  /**
   107.5 - * HTML via Java(tm) Language Bindings
   107.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   107.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   107.8   *
   107.9 - * This program is free software: you can redistribute it and/or modify
  107.10 - * it under the terms of the GNU General Public License as published by
  107.11 - * the Free Software Foundation, version 2 of the License.
  107.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  107.13   *
  107.14 - * This program is distributed in the hope that it will be useful,
  107.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  107.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  107.17 - * GNU General Public License for more details. apidesign.org
  107.18 - * designates this particular file as subject to the
  107.19 - * "Classpath" exception as provided by apidesign.org
  107.20 - * in the License file that accompanied this code.
  107.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  107.22 + * Other names may be trademarks of their respective owners.
  107.23   *
  107.24 - * You should have received a copy of the GNU General Public License
  107.25 - * along with this program. Look for COPYING file in the top folder.
  107.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  107.27 + * The contents of this file are subject to the terms of either the GNU
  107.28 + * General Public License Version 2 only ("GPL") or the Common
  107.29 + * Development and Distribution License("CDDL") (collectively, the
  107.30 + * "License"). You may not use this file except in compliance with the
  107.31 + * License. You can obtain a copy of the License at
  107.32 + * http://www.netbeans.org/cddl-gplv2.html
  107.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  107.34 + * specific language governing permissions and limitations under the
  107.35 + * License.  When distributing the software, include this License Header
  107.36 + * Notice in each file and include the License file at
  107.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  107.38 + * particular file as subject to the "Classpath" exception as provided
  107.39 + * by Oracle in the GPL Version 2 section of the License file that
  107.40 + * accompanied this code. If applicable, add the following below the
  107.41 + * License Header, with the fields enclosed by brackets [] replaced by
  107.42 + * your own identifying information:
  107.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  107.44 + *
  107.45 + * Contributor(s):
  107.46 + *
  107.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  107.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  107.49 + *
  107.50 + * If you wish your version of this file to be governed by only the CDDL
  107.51 + * or only the GPL Version 2, indicate your decision by adding
  107.52 + * "[Contributor] elects to include this software in this distribution
  107.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  107.54 + * single choice of license, a recipient has the option to distribute
  107.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  107.56 + * to extend the choice of license to its licensees as provided above.
  107.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  107.58 + * Version 2 license, then the option applies only if the new code is
  107.59 + * made subject to such option by the copyright holder.
  107.60   */
  107.61  package org.apidesign.html.json.tck;
  107.62  
   108.1 --- a/json-tck/src/main/java/org/apidesign/html/json/tck/KOTest.java	Thu Dec 19 17:11:01 2013 +0100
   108.2 +++ b/json-tck/src/main/java/org/apidesign/html/json/tck/KOTest.java	Tue Jan 07 08:21:57 2014 +0100
   108.3 @@ -1,22 +1,44 @@
   108.4  /**
   108.5 - * HTML via Java(tm) Language Bindings
   108.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   108.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   108.8   *
   108.9 - * This program is free software: you can redistribute it and/or modify
  108.10 - * it under the terms of the GNU General Public License as published by
  108.11 - * the Free Software Foundation, version 2 of the License.
  108.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  108.13   *
  108.14 - * This program is distributed in the hope that it will be useful,
  108.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  108.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  108.17 - * GNU General Public License for more details. apidesign.org
  108.18 - * designates this particular file as subject to the
  108.19 - * "Classpath" exception as provided by apidesign.org
  108.20 - * in the License file that accompanied this code.
  108.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  108.22 + * Other names may be trademarks of their respective owners.
  108.23   *
  108.24 - * You should have received a copy of the GNU General Public License
  108.25 - * along with this program. Look for COPYING file in the top folder.
  108.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  108.27 + * The contents of this file are subject to the terms of either the GNU
  108.28 + * General Public License Version 2 only ("GPL") or the Common
  108.29 + * Development and Distribution License("CDDL") (collectively, the
  108.30 + * "License"). You may not use this file except in compliance with the
  108.31 + * License. You can obtain a copy of the License at
  108.32 + * http://www.netbeans.org/cddl-gplv2.html
  108.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  108.34 + * specific language governing permissions and limitations under the
  108.35 + * License.  When distributing the software, include this License Header
  108.36 + * Notice in each file and include the License file at
  108.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  108.38 + * particular file as subject to the "Classpath" exception as provided
  108.39 + * by Oracle in the GPL Version 2 section of the License file that
  108.40 + * accompanied this code. If applicable, add the following below the
  108.41 + * License Header, with the fields enclosed by brackets [] replaced by
  108.42 + * your own identifying information:
  108.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  108.44 + *
  108.45 + * Contributor(s):
  108.46 + *
  108.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  108.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  108.49 + *
  108.50 + * If you wish your version of this file to be governed by only the CDDL
  108.51 + * or only the GPL Version 2, indicate your decision by adding
  108.52 + * "[Contributor] elects to include this software in this distribution
  108.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  108.54 + * single choice of license, a recipient has the option to distribute
  108.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  108.56 + * to extend the choice of license to its licensees as provided above.
  108.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  108.58 + * Version 2 license, then the option applies only if the new code is
  108.59 + * made subject to such option by the copyright holder.
  108.60   */
  108.61  package org.apidesign.html.json.tck;
  108.62  
   109.1 --- a/json-tck/src/main/java/org/apidesign/html/json/tck/KnockoutTCK.java	Thu Dec 19 17:11:01 2013 +0100
   109.2 +++ b/json-tck/src/main/java/org/apidesign/html/json/tck/KnockoutTCK.java	Tue Jan 07 08:21:57 2014 +0100
   109.3 @@ -1,22 +1,44 @@
   109.4  /**
   109.5 - * HTML via Java(tm) Language Bindings
   109.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   109.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   109.8   *
   109.9 - * This program is free software: you can redistribute it and/or modify
  109.10 - * it under the terms of the GNU General Public License as published by
  109.11 - * the Free Software Foundation, version 2 of the License.
  109.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  109.13   *
  109.14 - * This program is distributed in the hope that it will be useful,
  109.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  109.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  109.17 - * GNU General Public License for more details. apidesign.org
  109.18 - * designates this particular file as subject to the
  109.19 - * "Classpath" exception as provided by apidesign.org
  109.20 - * in the License file that accompanied this code.
  109.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  109.22 + * Other names may be trademarks of their respective owners.
  109.23   *
  109.24 - * You should have received a copy of the GNU General Public License
  109.25 - * along with this program. Look for COPYING file in the top folder.
  109.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  109.27 + * The contents of this file are subject to the terms of either the GNU
  109.28 + * General Public License Version 2 only ("GPL") or the Common
  109.29 + * Development and Distribution License("CDDL") (collectively, the
  109.30 + * "License"). You may not use this file except in compliance with the
  109.31 + * License. You can obtain a copy of the License at
  109.32 + * http://www.netbeans.org/cddl-gplv2.html
  109.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  109.34 + * specific language governing permissions and limitations under the
  109.35 + * License.  When distributing the software, include this License Header
  109.36 + * Notice in each file and include the License file at
  109.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  109.38 + * particular file as subject to the "Classpath" exception as provided
  109.39 + * by Oracle in the GPL Version 2 section of the License file that
  109.40 + * accompanied this code. If applicable, add the following below the
  109.41 + * License Header, with the fields enclosed by brackets [] replaced by
  109.42 + * your own identifying information:
  109.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  109.44 + *
  109.45 + * Contributor(s):
  109.46 + *
  109.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  109.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  109.49 + *
  109.50 + * If you wish your version of this file to be governed by only the CDDL
  109.51 + * or only the GPL Version 2, indicate your decision by adding
  109.52 + * "[Contributor] elects to include this software in this distribution
  109.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  109.54 + * single choice of license, a recipient has the option to distribute
  109.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  109.56 + * to extend the choice of license to its licensees as provided above.
  109.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  109.58 + * Version 2 license, then the option applies only if the new code is
  109.59 + * made subject to such option by the copyright holder.
  109.60   */
  109.61  package org.apidesign.html.json.tck;
  109.62  
  109.63 @@ -24,9 +46,10 @@
  109.64  import java.util.Map;
  109.65  import net.java.html.BrwsrCtx;
  109.66  import net.java.html.json.tests.ConvertTypesTest;
  109.67 +import net.java.html.json.tests.JSONTest;
  109.68  import net.java.html.json.tests.KnockoutTest;
  109.69 -import net.java.html.json.tests.JSONTest;
  109.70  import net.java.html.json.tests.OperationsTest;
  109.71 +import net.java.html.json.tests.Utils;
  109.72  import net.java.html.json.tests.WebSocketTest;
  109.73  import org.openide.util.lookup.ServiceProvider;
  109.74  
  109.75 @@ -50,6 +73,7 @@
  109.76   */
  109.77  public abstract class KnockoutTCK {
  109.78      protected KnockoutTCK() {
  109.79 +        Utils.registerTCK(this);
  109.80      }
  109.81      
  109.82      /** Implement to create new context for the test. 
   110.1 --- a/json-tck/src/main/resources/org/apidesign/html/json/tck/package.html	Thu Dec 19 17:11:01 2013 +0100
   110.2 +++ b/json-tck/src/main/resources/org/apidesign/html/json/tck/package.html	Tue Jan 07 08:21:57 2014 +0100
   110.3 @@ -1,23 +1,45 @@
   110.4  <!--
   110.5  
   110.6 -    HTML via Java(tm) Language Bindings
   110.7 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   110.8 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   110.9  
  110.10 -    This program is free software: you can redistribute it and/or modify
  110.11 -    it under the terms of the GNU General Public License as published by
  110.12 -    the Free Software Foundation, version 2 of the License.
  110.13 +    Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  110.14  
  110.15 -    This program is distributed in the hope that it will be useful,
  110.16 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
  110.17 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  110.18 -    GNU General Public License for more details. apidesign.org
  110.19 -    designates this particular file as subject to the
  110.20 -    "Classpath" exception as provided by apidesign.org
  110.21 -    in the License file that accompanied this code.
  110.22 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  110.23 +    Other names may be trademarks of their respective owners.
  110.24  
  110.25 -    You should have received a copy of the GNU General Public License
  110.26 -    along with this program. Look for COPYING file in the top folder.
  110.27 -    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  110.28 +    The contents of this file are subject to the terms of either the GNU
  110.29 +    General Public License Version 2 only ("GPL") or the Common
  110.30 +    Development and Distribution License("CDDL") (collectively, the
  110.31 +    "License"). You may not use this file except in compliance with the
  110.32 +    License. You can obtain a copy of the License at
  110.33 +    http://www.netbeans.org/cddl-gplv2.html
  110.34 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  110.35 +    specific language governing permissions and limitations under the
  110.36 +    License.  When distributing the software, include this License Header
  110.37 +    Notice in each file and include the License file at
  110.38 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  110.39 +    particular file as subject to the "Classpath" exception as provided
  110.40 +    by Oracle in the GPL Version 2 section of the License file that
  110.41 +    accompanied this code. If applicable, add the following below the
  110.42 +    License Header, with the fields enclosed by brackets [] replaced by
  110.43 +    your own identifying information:
  110.44 +    "Portions Copyrighted [year] [name of copyright owner]"
  110.45 +
  110.46 +    Contributor(s):
  110.47 +
  110.48 +    The Original Software is NetBeans. The Initial Developer of the Original
  110.49 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  110.50 +
  110.51 +    If you wish your version of this file to be governed by only the CDDL
  110.52 +    or only the GPL Version 2, indicate your decision by adding
  110.53 +    "[Contributor] elects to include this software in this distribution
  110.54 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
  110.55 +    single choice of license, a recipient has the option to distribute
  110.56 +    your version of this file under either the CDDL, the GPL Version 2 or
  110.57 +    to extend the choice of license to its licensees as provided above.
  110.58 +    However, if you add GPL Version 2 code and therefore, elected the GPL
  110.59 +    Version 2 license, then the option applies only if the new code is
  110.60 +    made subject to such option by the copyright holder.
  110.61  
  110.62  -->
  110.63  <!DOCTYPE html>
   111.1 --- a/json/pom.xml	Thu Dec 19 17:11:01 2013 +0100
   111.2 +++ b/json/pom.xml	Tue Jan 07 08:21:57 2014 +0100
   111.3 @@ -2,11 +2,11 @@
   111.4  <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">
   111.5    <modelVersion>4.0.0</modelVersion>
   111.6    <parent>
   111.7 -    <groupId>org.apidesign</groupId>
   111.8 -    <artifactId>html</artifactId>
   111.9 +    <groupId>org.netbeans.html</groupId>
  111.10 +    <artifactId>pom</artifactId>
  111.11      <version>0.7-SNAPSHOT</version>
  111.12    </parent>
  111.13 -  <groupId>org.apidesign.html</groupId>
  111.14 +  <groupId>org.netbeans.html</groupId>
  111.15    <artifactId>net.java.html.json</artifactId>
  111.16    <version>0.7-SNAPSHOT</version>
  111.17    <packaging>bundle</packaging>
   112.1 --- a/json/src/main/java/net/java/html/json/ComputedProperty.java	Thu Dec 19 17:11:01 2013 +0100
   112.2 +++ b/json/src/main/java/net/java/html/json/ComputedProperty.java	Tue Jan 07 08:21:57 2014 +0100
   112.3 @@ -1,22 +1,44 @@
   112.4  /**
   112.5 - * HTML via Java(tm) Language Bindings
   112.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   112.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   112.8   *
   112.9 - * This program is free software: you can redistribute it and/or modify
  112.10 - * it under the terms of the GNU General Public License as published by
  112.11 - * the Free Software Foundation, version 2 of the License.
  112.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  112.13   *
  112.14 - * This program is distributed in the hope that it will be useful,
  112.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  112.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  112.17 - * GNU General Public License for more details. apidesign.org
  112.18 - * designates this particular file as subject to the
  112.19 - * "Classpath" exception as provided by apidesign.org
  112.20 - * in the License file that accompanied this code.
  112.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  112.22 + * Other names may be trademarks of their respective owners.
  112.23   *
  112.24 - * You should have received a copy of the GNU General Public License
  112.25 - * along with this program. Look for COPYING file in the top folder.
  112.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  112.27 + * The contents of this file are subject to the terms of either the GNU
  112.28 + * General Public License Version 2 only ("GPL") or the Common
  112.29 + * Development and Distribution License("CDDL") (collectively, the
  112.30 + * "License"). You may not use this file except in compliance with the
  112.31 + * License. You can obtain a copy of the License at
  112.32 + * http://www.netbeans.org/cddl-gplv2.html
  112.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  112.34 + * specific language governing permissions and limitations under the
  112.35 + * License.  When distributing the software, include this License Header
  112.36 + * Notice in each file and include the License file at
  112.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  112.38 + * particular file as subject to the "Classpath" exception as provided
  112.39 + * by Oracle in the GPL Version 2 section of the License file that
  112.40 + * accompanied this code. If applicable, add the following below the
  112.41 + * License Header, with the fields enclosed by brackets [] replaced by
  112.42 + * your own identifying information:
  112.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  112.44 + *
  112.45 + * Contributor(s):
  112.46 + *
  112.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  112.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  112.49 + *
  112.50 + * If you wish your version of this file to be governed by only the CDDL
  112.51 + * or only the GPL Version 2, indicate your decision by adding
  112.52 + * "[Contributor] elects to include this software in this distribution
  112.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  112.54 + * single choice of license, a recipient has the option to distribute
  112.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  112.56 + * to extend the choice of license to its licensees as provided above.
  112.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  112.58 + * Version 2 license, then the option applies only if the new code is
  112.59 + * made subject to such option by the copyright holder.
  112.60   */
  112.61  package net.java.html.json;
  112.62  
   113.1 --- a/json/src/main/java/net/java/html/json/Function.java	Thu Dec 19 17:11:01 2013 +0100
   113.2 +++ b/json/src/main/java/net/java/html/json/Function.java	Tue Jan 07 08:21:57 2014 +0100
   113.3 @@ -1,22 +1,44 @@
   113.4  /**
   113.5 - * HTML via Java(tm) Language Bindings
   113.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   113.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   113.8   *
   113.9 - * This program is free software: you can redistribute it and/or modify
  113.10 - * it under the terms of the GNU General Public License as published by
  113.11 - * the Free Software Foundation, version 2 of the License.
  113.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  113.13   *
  113.14 - * This program is distributed in the hope that it will be useful,
  113.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  113.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  113.17 - * GNU General Public License for more details. apidesign.org
  113.18 - * designates this particular file as subject to the
  113.19 - * "Classpath" exception as provided by apidesign.org
  113.20 - * in the License file that accompanied this code.
  113.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  113.22 + * Other names may be trademarks of their respective owners.
  113.23   *
  113.24 - * You should have received a copy of the GNU General Public License
  113.25 - * along with this program. Look for COPYING file in the top folder.
  113.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  113.27 + * The contents of this file are subject to the terms of either the GNU
  113.28 + * General Public License Version 2 only ("GPL") or the Common
  113.29 + * Development and Distribution License("CDDL") (collectively, the
  113.30 + * "License"). You may not use this file except in compliance with the
  113.31 + * License. You can obtain a copy of the License at
  113.32 + * http://www.netbeans.org/cddl-gplv2.html
  113.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  113.34 + * specific language governing permissions and limitations under the
  113.35 + * License.  When distributing the software, include this License Header
  113.36 + * Notice in each file and include the License file at
  113.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  113.38 + * particular file as subject to the "Classpath" exception as provided
  113.39 + * by Oracle in the GPL Version 2 section of the License file that
  113.40 + * accompanied this code. If applicable, add the following below the
  113.41 + * License Header, with the fields enclosed by brackets [] replaced by
  113.42 + * your own identifying information:
  113.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  113.44 + *
  113.45 + * Contributor(s):
  113.46 + *
  113.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  113.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  113.49 + *
  113.50 + * If you wish your version of this file to be governed by only the CDDL
  113.51 + * or only the GPL Version 2, indicate your decision by adding
  113.52 + * "[Contributor] elects to include this software in this distribution
  113.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  113.54 + * single choice of license, a recipient has the option to distribute
  113.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  113.56 + * to extend the choice of license to its licensees as provided above.
  113.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  113.58 + * Version 2 license, then the option applies only if the new code is
  113.59 + * made subject to such option by the copyright holder.
  113.60   */
  113.61  package net.java.html.json;
  113.62  
   114.1 --- a/json/src/main/java/net/java/html/json/Model.java	Thu Dec 19 17:11:01 2013 +0100
   114.2 +++ b/json/src/main/java/net/java/html/json/Model.java	Tue Jan 07 08:21:57 2014 +0100
   114.3 @@ -1,22 +1,44 @@
   114.4  /**
   114.5 - * HTML via Java(tm) Language Bindings
   114.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   114.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   114.8   *
   114.9 - * This program is free software: you can redistribute it and/or modify
  114.10 - * it under the terms of the GNU General Public License as published by
  114.11 - * the Free Software Foundation, version 2 of the License.
  114.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  114.13   *
  114.14 - * This program is distributed in the hope that it will be useful,
  114.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  114.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  114.17 - * GNU General Public License for more details. apidesign.org
  114.18 - * designates this particular file as subject to the
  114.19 - * "Classpath" exception as provided by apidesign.org
  114.20 - * in the License file that accompanied this code.
  114.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  114.22 + * Other names may be trademarks of their respective owners.
  114.23   *
  114.24 - * You should have received a copy of the GNU General Public License
  114.25 - * along with this program. Look for COPYING file in the top folder.
  114.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  114.27 + * The contents of this file are subject to the terms of either the GNU
  114.28 + * General Public License Version 2 only ("GPL") or the Common
  114.29 + * Development and Distribution License("CDDL") (collectively, the
  114.30 + * "License"). You may not use this file except in compliance with the
  114.31 + * License. You can obtain a copy of the License at
  114.32 + * http://www.netbeans.org/cddl-gplv2.html
  114.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  114.34 + * specific language governing permissions and limitations under the
  114.35 + * License.  When distributing the software, include this License Header
  114.36 + * Notice in each file and include the License file at
  114.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  114.38 + * particular file as subject to the "Classpath" exception as provided
  114.39 + * by Oracle in the GPL Version 2 section of the License file that
  114.40 + * accompanied this code. If applicable, add the following below the
  114.41 + * License Header, with the fields enclosed by brackets [] replaced by
  114.42 + * your own identifying information:
  114.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  114.44 + *
  114.45 + * Contributor(s):
  114.46 + *
  114.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  114.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  114.49 + *
  114.50 + * If you wish your version of this file to be governed by only the CDDL
  114.51 + * or only the GPL Version 2, indicate your decision by adding
  114.52 + * "[Contributor] elects to include this software in this distribution
  114.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  114.54 + * single choice of license, a recipient has the option to distribute
  114.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  114.56 + * to extend the choice of license to its licensees as provided above.
  114.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  114.58 + * Version 2 license, then the option applies only if the new code is
  114.59 + * made subject to such option by the copyright holder.
  114.60   */
  114.61  package net.java.html.json;
  114.62  
   115.1 --- a/json/src/main/java/net/java/html/json/ModelOperation.java	Thu Dec 19 17:11:01 2013 +0100
   115.2 +++ b/json/src/main/java/net/java/html/json/ModelOperation.java	Tue Jan 07 08:21:57 2014 +0100
   115.3 @@ -1,22 +1,44 @@
   115.4  /**
   115.5 - * HTML via Java(tm) Language Bindings
   115.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   115.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   115.8   *
   115.9 - * This program is free software: you can redistribute it and/or modify
  115.10 - * it under the terms of the GNU General Public License as published by
  115.11 - * the Free Software Foundation, version 2 of the License.
  115.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  115.13   *
  115.14 - * This program is distributed in the hope that it will be useful,
  115.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  115.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  115.17 - * GNU General Public License for more details. apidesign.org
  115.18 - * designates this particular file as subject to the
  115.19 - * "Classpath" exception as provided by apidesign.org
  115.20 - * in the License file that accompanied this code.
  115.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  115.22 + * Other names may be trademarks of their respective owners.
  115.23   *
  115.24 - * You should have received a copy of the GNU General Public License
  115.25 - * along with this program. Look for COPYING file in the top folder.
  115.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  115.27 + * The contents of this file are subject to the terms of either the GNU
  115.28 + * General Public License Version 2 only ("GPL") or the Common
  115.29 + * Development and Distribution License("CDDL") (collectively, the
  115.30 + * "License"). You may not use this file except in compliance with the
  115.31 + * License. You can obtain a copy of the License at
  115.32 + * http://www.netbeans.org/cddl-gplv2.html
  115.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  115.34 + * specific language governing permissions and limitations under the
  115.35 + * License.  When distributing the software, include this License Header
  115.36 + * Notice in each file and include the License file at
  115.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  115.38 + * particular file as subject to the "Classpath" exception as provided
  115.39 + * by Oracle in the GPL Version 2 section of the License file that
  115.40 + * accompanied this code. If applicable, add the following below the
  115.41 + * License Header, with the fields enclosed by brackets [] replaced by
  115.42 + * your own identifying information:
  115.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  115.44 + *
  115.45 + * Contributor(s):
  115.46 + *
  115.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  115.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  115.49 + *
  115.50 + * If you wish your version of this file to be governed by only the CDDL
  115.51 + * or only the GPL Version 2, indicate your decision by adding
  115.52 + * "[Contributor] elects to include this software in this distribution
  115.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  115.54 + * single choice of license, a recipient has the option to distribute
  115.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  115.56 + * to extend the choice of license to its licensees as provided above.
  115.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  115.58 + * Version 2 license, then the option applies only if the new code is
  115.59 + * made subject to such option by the copyright holder.
  115.60   */
  115.61  package net.java.html.json;
  115.62  
   116.1 --- a/json/src/main/java/net/java/html/json/Models.java	Thu Dec 19 17:11:01 2013 +0100
   116.2 +++ b/json/src/main/java/net/java/html/json/Models.java	Tue Jan 07 08:21:57 2014 +0100
   116.3 @@ -1,29 +1,51 @@
   116.4  /**
   116.5 - * HTML via Java(tm) Language Bindings
   116.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   116.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   116.8   *
   116.9 - * This program is free software: you can redistribute it and/or modify
  116.10 - * it under the terms of the GNU General Public License as published by
  116.11 - * the Free Software Foundation, version 2 of the License.
  116.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  116.13   *
  116.14 - * This program is distributed in the hope that it will be useful,
  116.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  116.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  116.17 - * GNU General Public License for more details. apidesign.org
  116.18 - * designates this particular file as subject to the
  116.19 - * "Classpath" exception as provided by apidesign.org
  116.20 - * in the License file that accompanied this code.
  116.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  116.22 + * Other names may be trademarks of their respective owners.
  116.23   *
  116.24 - * You should have received a copy of the GNU General Public License
  116.25 - * along with this program. Look for COPYING file in the top folder.
  116.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  116.27 + * The contents of this file are subject to the terms of either the GNU
  116.28 + * General Public License Version 2 only ("GPL") or the Common
  116.29 + * Development and Distribution License("CDDL") (collectively, the
  116.30 + * "License"). You may not use this file except in compliance with the
  116.31 + * License. You can obtain a copy of the License at
  116.32 + * http://www.netbeans.org/cddl-gplv2.html
  116.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  116.34 + * specific language governing permissions and limitations under the
  116.35 + * License.  When distributing the software, include this License Header
  116.36 + * Notice in each file and include the License file at
  116.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  116.38 + * particular file as subject to the "Classpath" exception as provided
  116.39 + * by Oracle in the GPL Version 2 section of the License file that
  116.40 + * accompanied this code. If applicable, add the following below the
  116.41 + * License Header, with the fields enclosed by brackets [] replaced by
  116.42 + * your own identifying information:
  116.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  116.44 + *
  116.45 + * Contributor(s):
  116.46 + *
  116.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  116.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  116.49 + *
  116.50 + * If you wish your version of this file to be governed by only the CDDL
  116.51 + * or only the GPL Version 2, indicate your decision by adding
  116.52 + * "[Contributor] elects to include this software in this distribution
  116.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  116.54 + * single choice of license, a recipient has the option to distribute
  116.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  116.56 + * to extend the choice of license to its licensees as provided above.
  116.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  116.58 + * Version 2 license, then the option applies only if the new code is
  116.59 + * made subject to such option by the copyright holder.
  116.60   */
  116.61  package net.java.html.json;
  116.62  
  116.63  import net.java.html.BrwsrCtx;
  116.64  import java.io.IOException;
  116.65  import java.io.InputStream;
  116.66 -import org.apidesign.html.json.impl.JSON;
  116.67 +import org.netbeans.html.json.impl.JSON;
  116.68  
  116.69  /** Information about and 
  116.70   * operations for classes generated by the {@link Model @Model}
   117.1 --- a/json/src/main/java/net/java/html/json/OnPropertyChange.java	Thu Dec 19 17:11:01 2013 +0100
   117.2 +++ b/json/src/main/java/net/java/html/json/OnPropertyChange.java	Tue Jan 07 08:21:57 2014 +0100
   117.3 @@ -1,22 +1,44 @@
   117.4  /**
   117.5 - * HTML via Java(tm) Language Bindings
   117.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   117.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   117.8   *
   117.9 - * This program is free software: you can redistribute it and/or modify
  117.10 - * it under the terms of the GNU General Public License as published by
  117.11 - * the Free Software Foundation, version 2 of the License.
  117.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  117.13   *
  117.14 - * This program is distributed in the hope that it will be useful,
  117.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  117.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  117.17 - * GNU General Public License for more details. apidesign.org
  117.18 - * designates this particular file as subject to the
  117.19 - * "Classpath" exception as provided by apidesign.org
  117.20 - * in the License file that accompanied this code.
  117.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  117.22 + * Other names may be trademarks of their respective owners.
  117.23   *
  117.24 - * You should have received a copy of the GNU General Public License
  117.25 - * along with this program. Look for COPYING file in the top folder.
  117.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  117.27 + * The contents of this file are subject to the terms of either the GNU
  117.28 + * General Public License Version 2 only ("GPL") or the Common
  117.29 + * Development and Distribution License("CDDL") (collectively, the
  117.30 + * "License"). You may not use this file except in compliance with the
  117.31 + * License. You can obtain a copy of the License at
  117.32 + * http://www.netbeans.org/cddl-gplv2.html
  117.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  117.34 + * specific language governing permissions and limitations under the
  117.35 + * License.  When distributing the software, include this License Header
  117.36 + * Notice in each file and include the License file at
  117.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  117.38 + * particular file as subject to the "Classpath" exception as provided
  117.39 + * by Oracle in the GPL Version 2 section of the License file that
  117.40 + * accompanied this code. If applicable, add the following below the
  117.41 + * License Header, with the fields enclosed by brackets [] replaced by
  117.42 + * your own identifying information:
  117.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  117.44 + *
  117.45 + * Contributor(s):
  117.46 + *
  117.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  117.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  117.49 + *
  117.50 + * If you wish your version of this file to be governed by only the CDDL
  117.51 + * or only the GPL Version 2, indicate your decision by adding
  117.52 + * "[Contributor] elects to include this software in this distribution
  117.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  117.54 + * single choice of license, a recipient has the option to distribute
  117.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  117.56 + * to extend the choice of license to its licensees as provided above.
  117.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  117.58 + * Version 2 license, then the option applies only if the new code is
  117.59 + * made subject to such option by the copyright holder.
  117.60   */
  117.61  package net.java.html.json;
  117.62  
   118.1 --- a/json/src/main/java/net/java/html/json/OnReceive.java	Thu Dec 19 17:11:01 2013 +0100
   118.2 +++ b/json/src/main/java/net/java/html/json/OnReceive.java	Tue Jan 07 08:21:57 2014 +0100
   118.3 @@ -1,22 +1,44 @@
   118.4  /**
   118.5 - * HTML via Java(tm) Language Bindings
   118.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   118.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   118.8   *
   118.9 - * This program is free software: you can redistribute it and/or modify
  118.10 - * it under the terms of the GNU General Public License as published by
  118.11 - * the Free Software Foundation, version 2 of the License.
  118.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  118.13   *
  118.14 - * This program is distributed in the hope that it will be useful,
  118.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  118.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  118.17 - * GNU General Public License for more details. apidesign.org
  118.18 - * designates this particular file as subject to the
  118.19 - * "Classpath" exception as provided by apidesign.org
  118.20 - * in the License file that accompanied this code.
  118.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  118.22 + * Other names may be trademarks of their respective owners.
  118.23   *
  118.24 - * You should have received a copy of the GNU General Public License
  118.25 - * along with this program. Look for COPYING file in the top folder.
  118.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  118.27 + * The contents of this file are subject to the terms of either the GNU
  118.28 + * General Public License Version 2 only ("GPL") or the Common
  118.29 + * Development and Distribution License("CDDL") (collectively, the
  118.30 + * "License"). You may not use this file except in compliance with the
  118.31 + * License. You can obtain a copy of the License at
  118.32 + * http://www.netbeans.org/cddl-gplv2.html
  118.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  118.34 + * specific language governing permissions and limitations under the
  118.35 + * License.  When distributing the software, include this License Header
  118.36 + * Notice in each file and include the License file at
  118.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  118.38 + * particular file as subject to the "Classpath" exception as provided
  118.39 + * by Oracle in the GPL Version 2 section of the License file that
  118.40 + * accompanied this code. If applicable, add the following below the
  118.41 + * License Header, with the fields enclosed by brackets [] replaced by
  118.42 + * your own identifying information:
  118.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  118.44 + *
  118.45 + * Contributor(s):
  118.46 + *
  118.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  118.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  118.49 + *
  118.50 + * If you wish your version of this file to be governed by only the CDDL
  118.51 + * or only the GPL Version 2, indicate your decision by adding
  118.52 + * "[Contributor] elects to include this software in this distribution
  118.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  118.54 + * single choice of license, a recipient has the option to distribute
  118.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  118.56 + * to extend the choice of license to its licensees as provided above.
  118.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  118.58 + * Version 2 license, then the option applies only if the new code is
  118.59 + * made subject to such option by the copyright holder.
  118.60   */
  118.61  package net.java.html.json;
  118.62  
   119.1 --- a/json/src/main/java/net/java/html/json/Property.java	Thu Dec 19 17:11:01 2013 +0100
   119.2 +++ b/json/src/main/java/net/java/html/json/Property.java	Tue Jan 07 08:21:57 2014 +0100
   119.3 @@ -1,22 +1,44 @@
   119.4  /**
   119.5 - * HTML via Java(tm) Language Bindings
   119.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   119.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   119.8   *
   119.9 - * This program is free software: you can redistribute it and/or modify
  119.10 - * it under the terms of the GNU General Public License as published by
  119.11 - * the Free Software Foundation, version 2 of the License.
  119.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  119.13   *
  119.14 - * This program is distributed in the hope that it will be useful,
  119.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  119.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  119.17 - * GNU General Public License for more details. apidesign.org
  119.18 - * designates this particular file as subject to the
  119.19 - * "Classpath" exception as provided by apidesign.org
  119.20 - * in the License file that accompanied this code.
  119.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  119.22 + * Other names may be trademarks of their respective owners.
  119.23   *
  119.24 - * You should have received a copy of the GNU General Public License
  119.25 - * along with this program. Look for COPYING file in the top folder.
  119.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  119.27 + * The contents of this file are subject to the terms of either the GNU
  119.28 + * General Public License Version 2 only ("GPL") or the Common
  119.29 + * Development and Distribution License("CDDL") (collectively, the
  119.30 + * "License"). You may not use this file except in compliance with the
  119.31 + * License. You can obtain a copy of the License at
  119.32 + * http://www.netbeans.org/cddl-gplv2.html
  119.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  119.34 + * specific language governing permissions and limitations under the
  119.35 + * License.  When distributing the software, include this License Header
  119.36 + * Notice in each file and include the License file at
  119.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  119.38 + * particular file as subject to the "Classpath" exception as provided
  119.39 + * by Oracle in the GPL Version 2 section of the License file that
  119.40 + * accompanied this code. If applicable, add the following below the
  119.41 + * License Header, with the fields enclosed by brackets [] replaced by
  119.42 + * your own identifying information:
  119.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  119.44 + *
  119.45 + * Contributor(s):
  119.46 + *
  119.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  119.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  119.49 + *
  119.50 + * If you wish your version of this file to be governed by only the CDDL
  119.51 + * or only the GPL Version 2, indicate your decision by adding
  119.52 + * "[Contributor] elects to include this software in this distribution
  119.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  119.54 + * single choice of license, a recipient has the option to distribute
  119.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  119.56 + * to extend the choice of license to its licensees as provided above.
  119.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  119.58 + * Version 2 license, then the option applies only if the new code is
  119.59 + * made subject to such option by the copyright holder.
  119.60   */
  119.61  package net.java.html.json;
  119.62  
   120.1 --- a/json/src/main/java/net/java/html/json/doc-files/websockets.html	Thu Dec 19 17:11:01 2013 +0100
   120.2 +++ b/json/src/main/java/net/java/html/json/doc-files/websockets.html	Tue Jan 07 08:21:57 2014 +0100
   120.3 @@ -1,23 +1,45 @@
   120.4  <!--
   120.5  
   120.6 -    HTML via Java(tm) Language Bindings
   120.7 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   120.8 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   120.9  
  120.10 -    This program is free software: you can redistribute it and/or modify
  120.11 -    it under the terms of the GNU General Public License as published by
  120.12 -    the Free Software Foundation, version 2 of the License.
  120.13 +    Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  120.14  
  120.15 -    This program is distributed in the hope that it will be useful,
  120.16 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
  120.17 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  120.18 -    GNU General Public License for more details. apidesign.org
  120.19 -    designates this particular file as subject to the
  120.20 -    "Classpath" exception as provided by apidesign.org
  120.21 -    in the License file that accompanied this code.
  120.22 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  120.23 +    Other names may be trademarks of their respective owners.
  120.24  
  120.25 -    You should have received a copy of the GNU General Public License
  120.26 -    along with this program. Look for COPYING file in the top folder.
  120.27 -    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  120.28 +    The contents of this file are subject to the terms of either the GNU
  120.29 +    General Public License Version 2 only ("GPL") or the Common
  120.30 +    Development and Distribution License("CDDL") (collectively, the
  120.31 +    "License"). You may not use this file except in compliance with the
  120.32 +    License. You can obtain a copy of the License at
  120.33 +    http://www.netbeans.org/cddl-gplv2.html
  120.34 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  120.35 +    specific language governing permissions and limitations under the
  120.36 +    License.  When distributing the software, include this License Header
  120.37 +    Notice in each file and include the License file at
  120.38 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  120.39 +    particular file as subject to the "Classpath" exception as provided
  120.40 +    by Oracle in the GPL Version 2 section of the License file that
  120.41 +    accompanied this code. If applicable, add the following below the
  120.42 +    License Header, with the fields enclosed by brackets [] replaced by
  120.43 +    your own identifying information:
  120.44 +    "Portions Copyrighted [year] [name of copyright owner]"
  120.45 +
  120.46 +    Contributor(s):
  120.47 +
  120.48 +    The Original Software is NetBeans. The Initial Developer of the Original
  120.49 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  120.50 +
  120.51 +    If you wish your version of this file to be governed by only the CDDL
  120.52 +    or only the GPL Version 2, indicate your decision by adding
  120.53 +    "[Contributor] elects to include this software in this distribution
  120.54 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
  120.55 +    single choice of license, a recipient has the option to distribute
  120.56 +    your version of this file under either the CDDL, the GPL Version 2 or
  120.57 +    to extend the choice of license to its licensees as provided above.
  120.58 +    However, if you add GPL Version 2 code and therefore, elected the GPL
  120.59 +    Version 2 license, then the option applies only if the new code is
  120.60 +    made subject to such option by the copyright holder.
  120.61  
  120.62  -->
  120.63  <!DOCTYPE html>
   121.1 --- a/json/src/main/java/net/java/html/json/package.html	Thu Dec 19 17:11:01 2013 +0100
   121.2 +++ b/json/src/main/java/net/java/html/json/package.html	Tue Jan 07 08:21:57 2014 +0100
   121.3 @@ -1,23 +1,45 @@
   121.4  <!--
   121.5  
   121.6 -    HTML via Java(tm) Language Bindings
   121.7 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   121.8 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   121.9  
  121.10 -    This program is free software: you can redistribute it and/or modify
  121.11 -    it under the terms of the GNU General Public License as published by
  121.12 -    the Free Software Foundation, version 2 of the License.
  121.13 +    Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  121.14  
  121.15 -    This program is distributed in the hope that it will be useful,
  121.16 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
  121.17 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  121.18 -    GNU General Public License for more details. apidesign.org
  121.19 -    designates this particular file as subject to the
  121.20 -    "Classpath" exception as provided by apidesign.org
  121.21 -    in the License file that accompanied this code.
  121.22 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  121.23 +    Other names may be trademarks of their respective owners.
  121.24  
  121.25 -    You should have received a copy of the GNU General Public License
  121.26 -    along with this program. Look for COPYING file in the top folder.
  121.27 -    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  121.28 +    The contents of this file are subject to the terms of either the GNU
  121.29 +    General Public License Version 2 only ("GPL") or the Common
  121.30 +    Development and Distribution License("CDDL") (collectively, the
  121.31 +    "License"). You may not use this file except in compliance with the
  121.32 +    License. You can obtain a copy of the License at
  121.33 +    http://www.netbeans.org/cddl-gplv2.html
  121.34 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  121.35 +    specific language governing permissions and limitations under the
  121.36 +    License.  When distributing the software, include this License Header
  121.37 +    Notice in each file and include the License file at
  121.38 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  121.39 +    particular file as subject to the "Classpath" exception as provided
  121.40 +    by Oracle in the GPL Version 2 section of the License file that
  121.41 +    accompanied this code. If applicable, add the following below the
  121.42 +    License Header, with the fields enclosed by brackets [] replaced by
  121.43 +    your own identifying information:
  121.44 +    "Portions Copyrighted [year] [name of copyright owner]"
  121.45 +
  121.46 +    Contributor(s):
  121.47 +
  121.48 +    The Original Software is NetBeans. The Initial Developer of the Original
  121.49 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  121.50 +
  121.51 +    If you wish your version of this file to be governed by only the CDDL
  121.52 +    or only the GPL Version 2, indicate your decision by adding
  121.53 +    "[Contributor] elects to include this software in this distribution
  121.54 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
  121.55 +    single choice of license, a recipient has the option to distribute
  121.56 +    your version of this file under either the CDDL, the GPL Version 2 or
  121.57 +    to extend the choice of license to its licensees as provided above.
  121.58 +    However, if you add GPL Version 2 code and therefore, elected the GPL
  121.59 +    Version 2 license, then the option applies only if the new code is
  121.60 +    made subject to such option by the copyright holder.
  121.61  
  121.62  -->
  121.63  <body>
   122.1 --- a/json/src/main/java/org/apidesign/html/json/impl/Bindings.java	Thu Dec 19 17:11:01 2013 +0100
   122.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   122.3 @@ -1,91 +0,0 @@
   122.4 -/**
   122.5 - * HTML via Java(tm) Language Bindings
   122.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   122.7 - *
   122.8 - * This program is free software: you can redistribute it and/or modify
   122.9 - * it under the terms of the GNU General Public License as published by
  122.10 - * the Free Software Foundation, version 2 of the License.
  122.11 - *
  122.12 - * This program is distributed in the hope that it will be useful,
  122.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  122.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  122.15 - * GNU General Public License for more details. apidesign.org
  122.16 - * designates this particular file as subject to the
  122.17 - * "Classpath" exception as provided by apidesign.org
  122.18 - * in the License file that accompanied this code.
  122.19 - *
  122.20 - * You should have received a copy of the GNU General Public License
  122.21 - * along with this program. Look for COPYING file in the top folder.
  122.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  122.23 - */
  122.24 -package org.apidesign.html.json.impl;
  122.25 -
  122.26 -import org.apidesign.html.json.spi.PropertyBinding;
  122.27 -import net.java.html.BrwsrCtx;
  122.28 -import org.apidesign.html.json.impl.PropertyBindingAccessor.FBData;
  122.29 -import org.apidesign.html.json.impl.PropertyBindingAccessor.PBData;
  122.30 -import org.apidesign.html.json.spi.FunctionBinding;
  122.31 -import org.apidesign.html.json.spi.Technology;
  122.32 -
  122.33 -/**
  122.34 - *
  122.35 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  122.36 - */
  122.37 -public final class Bindings<Data> {
  122.38 -    private Data data;
  122.39 -    private final Technology<Data> bp;
  122.40 -
  122.41 -    private Bindings(Technology<Data> bp) {
  122.42 -        this.bp = bp;
  122.43 -    }
  122.44 -    
  122.45 -    public <M> PropertyBinding registerProperty(String propName, M model, SetAndGet<M> access, boolean readOnly) {
  122.46 -        return PropertyBindingAccessor.create(new PBData<M>(this, propName, model, access, readOnly));
  122.47 -    }
  122.48 -
  122.49 -    public <M> FunctionBinding registerFunction(String name, M model, Callback<M> access) {
  122.50 -        return PropertyBindingAccessor.createFunction(new FBData<M>(name, model, access));
  122.51 -    }
  122.52 -    
  122.53 -    public static Bindings<?> apply(BrwsrCtx c, Object model) {
  122.54 -        Technology<?> bp = JSON.findTechnology(c);
  122.55 -        return apply(bp);
  122.56 -    }
  122.57 -    
  122.58 -    private static <Data> Bindings<Data> apply(Technology<Data> bp) {
  122.59 -        return new Bindings<Data>(bp);
  122.60 -    }
  122.61 -    
  122.62 -    public final void finish(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
  122.63 -        assert data == null;
  122.64 -        if (bp instanceof Technology.BatchInit) {
  122.65 -            Technology.BatchInit<Data> bi = (Technology.BatchInit<Data>)bp;
  122.66 -            data = bi.wrapModel(model, propArr, funcArr);
  122.67 -        } else {
  122.68 -            data = bp.wrapModel(model);
  122.69 -            for (PropertyBinding b : propArr) {
  122.70 -                bp.bind(b, model, data);
  122.71 -            }
  122.72 -            for (FunctionBinding b : funcArr) {
  122.73 -                bp.expose(b, model, data);
  122.74 -            }
  122.75 -        }
  122.76 -    }
  122.77 -    
  122.78 -    
  122.79 -    public Data koData() {
  122.80 -        return data;
  122.81 -    }
  122.82 -
  122.83 -    public void valueHasMutated(String firstName) {
  122.84 -        bp.valueHasMutated(data, firstName);
  122.85 -    }
  122.86 -    
  122.87 -    public void applyBindings() {
  122.88 -        bp.applyBindings(data);
  122.89 -    }
  122.90 -
  122.91 -    Object wrapArray(Object[] arr) {
  122.92 -        return bp.wrapArray(arr);
  122.93 -    }
  122.94 -}
   123.1 --- a/json/src/main/java/org/apidesign/html/json/impl/Callback.java	Thu Dec 19 17:11:01 2013 +0100
   123.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   123.3 @@ -1,30 +0,0 @@
   123.4 -/**
   123.5 - * HTML via Java(tm) Language Bindings
   123.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   123.7 - *
   123.8 - * This program is free software: you can redistribute it and/or modify
   123.9 - * it under the terms of the GNU General Public License as published by
  123.10 - * the Free Software Foundation, version 2 of the License.
  123.11 - *
  123.12 - * This program is distributed in the hope that it will be useful,
  123.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  123.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  123.15 - * GNU General Public License for more details. apidesign.org
  123.16 - * designates this particular file as subject to the
  123.17 - * "Classpath" exception as provided by apidesign.org
  123.18 - * in the License file that accompanied this code.
  123.19 - *
  123.20 - * You should have received a copy of the GNU General Public License
  123.21 - * along with this program. Look for COPYING file in the top folder.
  123.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  123.23 - */
  123.24 -
  123.25 -package org.apidesign.html.json.impl;
  123.26 -
  123.27 -/**
  123.28 - *
  123.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  123.30 - */
  123.31 -public interface Callback<Data> {
  123.32 -    public void call(Data model, Object data, Object ev);
  123.33 -}
   124.1 --- a/json/src/main/java/org/apidesign/html/json/impl/FromJSON.java	Thu Dec 19 17:11:01 2013 +0100
   124.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   124.3 @@ -1,34 +0,0 @@
   124.4 -/**
   124.5 - * HTML via Java(tm) Language Bindings
   124.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   124.7 - *
   124.8 - * This program is free software: you can redistribute it and/or modify
   124.9 - * it under the terms of the GNU General Public License as published by
  124.10 - * the Free Software Foundation, version 2 of the License.
  124.11 - *
  124.12 - * This program is distributed in the hope that it will be useful,
  124.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  124.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  124.15 - * GNU General Public License for more details. apidesign.org
  124.16 - * designates this particular file as subject to the
  124.17 - * "Classpath" exception as provided by apidesign.org
  124.18 - * in the License file that accompanied this code.
  124.19 - *
  124.20 - * You should have received a copy of the GNU General Public License
  124.21 - * along with this program. Look for COPYING file in the top folder.
  124.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  124.23 - */
  124.24 -
  124.25 -package org.apidesign.html.json.impl;
  124.26 -
  124.27 -import net.java.html.BrwsrCtx;
  124.28 -
  124.29 -/**
  124.30 - *
  124.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  124.32 - */
  124.33 -public interface FromJSON<Data> {
  124.34 -    public Class<Data> factoryFor();
  124.35 -    public Data read(BrwsrCtx c, Object d);
  124.36 -    public Data cloneTo(Object d, BrwsrCtx c);
  124.37 -}
   125.1 --- a/json/src/main/java/org/apidesign/html/json/impl/JSON.java	Thu Dec 19 17:11:01 2013 +0100
   125.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   125.3 @@ -1,452 +0,0 @@
   125.4 -/**
   125.5 - * HTML via Java(tm) Language Bindings
   125.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   125.7 - *
   125.8 - * This program is free software: you can redistribute it and/or modify
   125.9 - * it under the terms of the GNU General Public License as published by
  125.10 - * the Free Software Foundation, version 2 of the License.
  125.11 - *
  125.12 - * This program is distributed in the hope that it will be useful,
  125.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  125.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  125.15 - * GNU General Public License for more details. apidesign.org
  125.16 - * designates this particular file as subject to the
  125.17 - * "Classpath" exception as provided by apidesign.org
  125.18 - * in the License file that accompanied this code.
  125.19 - *
  125.20 - * You should have received a copy of the GNU General Public License
  125.21 - * along with this program. Look for COPYING file in the top folder.
  125.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  125.23 - */
  125.24 -package org.apidesign.html.json.impl;
  125.25 -
  125.26 -import java.io.IOException;
  125.27 -import java.io.InputStream;
  125.28 -import java.util.HashMap;
  125.29 -import java.util.Map;
  125.30 -import net.java.html.BrwsrCtx;
  125.31 -import org.apidesign.html.context.spi.Contexts;
  125.32 -import org.apidesign.html.json.spi.FunctionBinding;
  125.33 -import org.apidesign.html.json.spi.JSONCall;
  125.34 -import org.apidesign.html.json.spi.PropertyBinding;
  125.35 -import org.apidesign.html.json.spi.Technology;
  125.36 -import org.apidesign.html.json.spi.Transfer;
  125.37 -import org.apidesign.html.json.spi.WSTransfer;
  125.38 -
  125.39 -/**
  125.40 - *
  125.41 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  125.42 - */
  125.43 -public final class JSON {
  125.44 -    private JSON() {
  125.45 -    }
  125.46 -
  125.47 -    static Technology<?> findTechnology(BrwsrCtx c) {
  125.48 -        Technology<?> t = Contexts.find(c, Technology.class);
  125.49 -        return t == null ? EmptyTech.EMPTY : t;
  125.50 -    }
  125.51 -
  125.52 -    static Transfer findTransfer(BrwsrCtx c) {
  125.53 -        Transfer t = Contexts.find(c, Transfer.class);
  125.54 -        return t == null ? EmptyTech.EMPTY : t;
  125.55 -    }
  125.56 -
  125.57 -    static WSTransfer<?> findWSTransfer(BrwsrCtx c) {
  125.58 -        WSTransfer<?> t = Contexts.find(c, WSTransfer.class);
  125.59 -        return t == null ? EmptyTech.EMPTY : t;
  125.60 -    }
  125.61 -    
  125.62 -    public static void runInBrowser(BrwsrCtx c, Runnable runnable) {
  125.63 -        findTechnology(c).runSafe(runnable);
  125.64 -    }
  125.65 -    
  125.66 -    public static void extract(BrwsrCtx c, Object value, String[] props, Object[] values) {
  125.67 -        Transfer t = findTransfer(c);
  125.68 -        t.extract(value, props, values);
  125.69 -    }
  125.70 -    
  125.71 -    private static Object getProperty(BrwsrCtx c, Object obj, String prop) {
  125.72 -        if (prop == null) return obj;
  125.73 -        
  125.74 -        String[] arr = { prop };
  125.75 -        Object[] val = { null };
  125.76 -        extract(c, obj, arr, val);
  125.77 -        return val[0];
  125.78 -    }
  125.79 -
  125.80 -    public static Object toJSON(Object value) {
  125.81 -        if (value == null) {
  125.82 -            return "null";
  125.83 -        }
  125.84 -        if (value instanceof Enum) {
  125.85 -            value = value.toString();
  125.86 -        }
  125.87 -        if (value instanceof String) {
  125.88 -            String s = (String)value;
  125.89 -            int len = s.length();
  125.90 -            StringBuilder sb = new StringBuilder(len + 10);
  125.91 -            sb.append('"');
  125.92 -            for (int i = 0; i < len; i++) {
  125.93 -                char ch = s.charAt(i);
  125.94 -                switch (ch) {
  125.95 -                    case '\"': sb.append("\\\""); break;
  125.96 -                    case '\n': sb.append("\\n"); break;
  125.97 -                    case '\r': sb.append("\\r"); break;
  125.98 -                    case '\t': sb.append("\\t"); break;
  125.99 -                    case '\\': sb.append("\\\\"); break;
 125.100 -                    default: sb.append(ch);
 125.101 -                }
 125.102 -            }
 125.103 -            sb.append('"');
 125.104 -            return sb.toString();
 125.105 -        }
 125.106 -        return value.toString();
 125.107 -    }
 125.108 -
 125.109 -    public static String toString(BrwsrCtx c, Object obj, String prop) {
 125.110 -        obj = getProperty(c, obj, prop);
 125.111 -        return obj instanceof String ? (String)obj : null;
 125.112 -    }
 125.113 -    public static Number toNumber(BrwsrCtx c, Object obj, String prop) {
 125.114 -        obj = getProperty(c, obj, prop);
 125.115 -        if (!(obj instanceof Number)) {
 125.116 -            obj = Double.NaN;
 125.117 -        }
 125.118 -        return (Number)obj;
 125.119 -    }
 125.120 -    public static <M> M toModel(BrwsrCtx c, Class<M> aClass, Object data, Object object) {
 125.121 -        Technology<?> t = findTechnology(c);
 125.122 -        Object o = t.toModel(aClass, data);
 125.123 -        return aClass.cast(o);
 125.124 -    }
 125.125 -    
 125.126 -    public static boolean isSame(int a, int b) {
 125.127 -        return a == b;
 125.128 -    }
 125.129 -    
 125.130 -    public static boolean isSame(double a, double b) {
 125.131 -        return a == b;
 125.132 -    }
 125.133 -    
 125.134 -    public static boolean isSame(Object a, Object b) {
 125.135 -        if (a == b) {
 125.136 -            return true;
 125.137 -        }
 125.138 -        if (a == null || b == null) {
 125.139 -            return false;
 125.140 -        }
 125.141 -        return a.equals(b);
 125.142 -    }
 125.143 -    
 125.144 -    public static int hashPlus(Object o, int h) {
 125.145 -        return o == null ? h : h ^ o.hashCode();
 125.146 -    }
 125.147 -
 125.148 -    public static <T> T extractValue(Class<T> type, Object val) {
 125.149 -        if (Number.class.isAssignableFrom(type)) {
 125.150 -            val = numberValue(val);
 125.151 -        }
 125.152 -        if (Boolean.class == type) {
 125.153 -            val = boolValue(val);
 125.154 -        }
 125.155 -        if (String.class == type) {
 125.156 -            val = stringValue(val);
 125.157 -        }
 125.158 -        if (Character.class == type) {
 125.159 -            val = charValue(val);
 125.160 -        }
 125.161 -        if (Integer.class == type) {
 125.162 -            val = val instanceof Number ? ((Number)val).intValue() : 0;
 125.163 -        }
 125.164 -        if (Long.class == type) {
 125.165 -            val = val instanceof Number  ? ((Number)val).longValue() : 0;
 125.166 -        }
 125.167 -        if (Short.class == type) {
 125.168 -            val = val instanceof Number ? ((Number)val).shortValue() : 0;
 125.169 -        }
 125.170 -        if (Byte.class == type) {
 125.171 -            val = val instanceof Number ? ((Number)val).byteValue() : 0;
 125.172 -        }        
 125.173 -        if (Double.class == type) {
 125.174 -            val = val instanceof Number ? ((Number)val).doubleValue() : Double.NaN;
 125.175 -        }
 125.176 -        if (Float.class == type) {
 125.177 -            val = val instanceof Number ? ((Number)val).floatValue() : Float.NaN;
 125.178 -        }
 125.179 -        return type.cast(val);
 125.180 -    }
 125.181 -    
 125.182 -    protected static boolean isNumeric(Object val) {
 125.183 -        return ((val instanceof Integer) || (val instanceof Long) || (val instanceof Short) || (val instanceof Byte));
 125.184 -    }
 125.185 -    
 125.186 -    public static String stringValue(Object val) {
 125.187 -        if (val instanceof Boolean) {
 125.188 -            return ((Boolean)val ? "true" : "false");
 125.189 -        }
 125.190 -        if (isNumeric(val)) {
 125.191 -            return Long.toString(((Number)val).longValue());
 125.192 -        }
 125.193 -        if (val instanceof Float) {
 125.194 -            return Float.toString((Float)val);
 125.195 -        }
 125.196 -        if (val instanceof Double) {
 125.197 -            return Double.toString((Double)val);
 125.198 -        }
 125.199 -        return (String)val;
 125.200 -    }
 125.201 -
 125.202 -    public static Number numberValue(Object val) {
 125.203 -        if (val instanceof String) {
 125.204 -            try {
 125.205 -                return Double.valueOf((String)val);
 125.206 -            } catch (NumberFormatException ex) {
 125.207 -                return Double.NaN;
 125.208 -            }
 125.209 -        }
 125.210 -        if (val instanceof Boolean) {
 125.211 -            return (Boolean)val ? 1 : 0;
 125.212 -        }
 125.213 -        return (Number)val;
 125.214 -    }
 125.215 -
 125.216 -    public static Character charValue(Object val) {
 125.217 -        if (val instanceof Number) {
 125.218 -            return Character.toChars(numberValue(val).intValue())[0];
 125.219 -        }
 125.220 -        if (val instanceof Boolean) {
 125.221 -            return (Boolean)val ? (char)1 : (char)0;
 125.222 -        }
 125.223 -        if (val instanceof String) {
 125.224 -            String s = (String)val;
 125.225 -            return s.isEmpty() ? (char)0 : s.charAt(0);
 125.226 -        }
 125.227 -        return (Character)val;
 125.228 -    }
 125.229 -    
 125.230 -    public static Boolean boolValue(Object val) {
 125.231 -        if (val instanceof String) {
 125.232 -            return Boolean.parseBoolean((String)val);
 125.233 -        }
 125.234 -        if (val instanceof Number) {
 125.235 -            return numberValue(val).doubleValue() != 0.0;
 125.236 -        }
 125.237 -    
 125.238 -        return Boolean.TRUE.equals(val);
 125.239 -    }
 125.240 -    
 125.241 -    public static void loadJSON(
 125.242 -        BrwsrCtx c, RcvrJSON callback,
 125.243 -        String urlBefore, String urlAfter, String method,
 125.244 -        Object data
 125.245 -    ) {
 125.246 -        JSONCall call = PropertyBindingAccessor.createCall(c, callback, urlBefore, urlAfter, method, data);
 125.247 -        Transfer t = findTransfer(c);
 125.248 -        t.loadJSON(call);
 125.249 -    }
 125.250 -    public static WS openWS(
 125.251 -        BrwsrCtx c, RcvrJSON r, String url, Object data
 125.252 -    ) {
 125.253 -        WS ws = WSImpl.create(findWSTransfer(c), r);
 125.254 -        ws.send(c, url, data);
 125.255 -        return ws;
 125.256 -    }
 125.257 -    
 125.258 -    public static abstract class WS {
 125.259 -        private WS() {
 125.260 -        }
 125.261 -        
 125.262 -        public abstract void send(BrwsrCtx ctx, String url, Object model);
 125.263 -    }
 125.264 -    
 125.265 -    private static final class WSImpl<Socket> extends WS {
 125.266 -
 125.267 -        private final WSTransfer<Socket> trans;
 125.268 -        private final RcvrJSON rcvr;
 125.269 -        private Socket socket;
 125.270 -        private String prevURL;
 125.271 -
 125.272 -        private WSImpl(WSTransfer<Socket> trans, RcvrJSON rcvr) {
 125.273 -            this.trans = trans;
 125.274 -            this.rcvr = rcvr;
 125.275 -        }
 125.276 -        
 125.277 -        static <Socket> WS create(WSTransfer<Socket> t, RcvrJSON r) {
 125.278 -            return new WSImpl<Socket>(t, r);
 125.279 -        }
 125.280 -
 125.281 -        @Override
 125.282 -        public void send(BrwsrCtx ctx, String url, Object data) {
 125.283 -            Socket s = socket;
 125.284 -            if (s == null) {
 125.285 -                if (data != null) {
 125.286 -                    throw new IllegalStateException("WebSocket is not opened yet. Call with null data, was: " + data);
 125.287 -                }
 125.288 -                JSONCall call = PropertyBindingAccessor.createCall(ctx, rcvr, url, null, "WebSocket", null);
 125.289 -                socket = trans.open(url, call);
 125.290 -                prevURL = url;
 125.291 -                return;
 125.292 -            }
 125.293 -            if (data == null) {
 125.294 -                trans.close(s);
 125.295 -                socket = null;
 125.296 -                return;
 125.297 -            }
 125.298 -            if (!prevURL.equals(url)) {
 125.299 -                throw new IllegalStateException(
 125.300 -                    "Can't call to different URL " + url + " was: " + prevURL + "!"
 125.301 -                    + " Close the socket by calling it will null data first!"
 125.302 -                );
 125.303 -            }
 125.304 -            JSONCall call = PropertyBindingAccessor.createCall(ctx, rcvr, prevURL, null, "WebSocket", data);
 125.305 -            trans.send(s, call);
 125.306 -        }
 125.307 -        
 125.308 -    }
 125.309 -    
 125.310 -    private static final Map<Class,FromJSON<?>> froms;
 125.311 -    static {
 125.312 -        Map<Class,FromJSON<?>> m = new HashMap<Class,FromJSON<?>>();
 125.313 -        froms = m;
 125.314 -    }
 125.315 -    public static void register(FromJSON<?> from) {
 125.316 -        froms.put(from.factoryFor(), from);
 125.317 -    }
 125.318 -    
 125.319 -    public static boolean isModel(Class<?> clazz) {
 125.320 -        return findFrom(clazz) != null; 
 125.321 -    }
 125.322 -    
 125.323 -    private static FromJSON<?> findFrom(Class<?> clazz) {
 125.324 -        for (int i = 0; i < 2; i++) {
 125.325 -            FromJSON<?> from = froms.get(clazz);
 125.326 -            if (from == null) {
 125.327 -                initClass(clazz);
 125.328 -            } else {
 125.329 -                return from;
 125.330 -            }
 125.331 -        }
 125.332 -        return null;
 125.333 -    }
 125.334 -    
 125.335 -    public static <Model> Model bindTo(Model model, BrwsrCtx c) {
 125.336 -        FromJSON<?> from = findFrom(model.getClass());
 125.337 -        if (from == null) {
 125.338 -            throw new IllegalArgumentException();
 125.339 -        }
 125.340 -        return (Model) from.cloneTo(model, c);
 125.341 -    }
 125.342 -    
 125.343 -    public static <T> T readStream(BrwsrCtx c, Class<T> modelClazz, InputStream data) 
 125.344 -    throws IOException {
 125.345 -        Transfer tr = findTransfer(c);
 125.346 -        return read(c, modelClazz, tr.toJSON((InputStream)data));
 125.347 -    }
 125.348 -    public static <T> T read(BrwsrCtx c, Class<T> modelClazz, Object data) {
 125.349 -        if (data == null) {
 125.350 -            return null;
 125.351 -        }
 125.352 -        if (modelClazz == String.class) {
 125.353 -            return modelClazz.cast(data.toString());
 125.354 -        }
 125.355 -        for (int i = 0; i < 2; i++) {
 125.356 -            FromJSON<?> from = froms.get(modelClazz);
 125.357 -            if (from == null) {
 125.358 -                initClass(modelClazz);
 125.359 -            } else {
 125.360 -                return modelClazz.cast(from.read(c, data));
 125.361 -            }
 125.362 -        }
 125.363 -        throw new NullPointerException();
 125.364 -    }
 125.365 -    static void initClass(Class<?> modelClazz) {
 125.366 -        try {
 125.367 -            // try to resolve the class
 125.368 -            ClassLoader l;
 125.369 -            try {
 125.370 -                l = modelClazz.getClassLoader();
 125.371 -            } catch (SecurityException ex) {
 125.372 -                l = null;
 125.373 -            }
 125.374 -            if (l != null) {
 125.375 -                Class.forName(modelClazz.getName(), true, l);
 125.376 -            }
 125.377 -            modelClazz.newInstance();
 125.378 -        } catch (Exception ex) {
 125.379 -            // ignore and try again
 125.380 -        }
 125.381 -    }
 125.382 -    
 125.383 -    private static final class EmptyTech
 125.384 -    implements Technology<Object>, Transfer, WSTransfer<Void> {
 125.385 -        private static final EmptyTech EMPTY = new EmptyTech();
 125.386 -
 125.387 -        @Override
 125.388 -        public Object wrapModel(Object model) {
 125.389 -            return model;
 125.390 -        }
 125.391 -
 125.392 -        @Override
 125.393 -        public void valueHasMutated(Object data, String propertyName) {
 125.394 -        }
 125.395 -
 125.396 -        @Override
 125.397 -        public void bind(PropertyBinding b, Object model, Object data) {
 125.398 -        }
 125.399 -
 125.400 -        @Override
 125.401 -        public void expose(FunctionBinding fb, Object model, Object d) {
 125.402 -        }
 125.403 -
 125.404 -        @Override
 125.405 -        public void applyBindings(Object data) {
 125.406 -        }
 125.407 -
 125.408 -        @Override
 125.409 -        public Object wrapArray(Object[] arr) {
 125.410 -            return arr;
 125.411 -        }
 125.412 -
 125.413 -        @Override
 125.414 -        public void extract(Object obj, String[] props, Object[] values) {
 125.415 -            for (int i = 0; i < values.length; i++) {
 125.416 -                values[i] = null;
 125.417 -            }
 125.418 -        }
 125.419 -
 125.420 -        @Override
 125.421 -        public void loadJSON(JSONCall call) {
 125.422 -            call.notifyError(new UnsupportedOperationException());
 125.423 -        }
 125.424 -
 125.425 -        @Override
 125.426 -        public <M> M toModel(Class<M> modelClass, Object data) {
 125.427 -            return modelClass.cast(data);
 125.428 -        }
 125.429 -
 125.430 -        @Override
 125.431 -        public Object toJSON(InputStream is) throws IOException {
 125.432 -            throw new IOException("Not supported");
 125.433 -        }
 125.434 -
 125.435 -        @Override
 125.436 -        public synchronized void runSafe(Runnable r) {
 125.437 -            r.run();
 125.438 -        }
 125.439 -
 125.440 -        @Override
 125.441 -        public Void open(String url, JSONCall onReply) {
 125.442 -            onReply.notifyError(new UnsupportedOperationException("WebSockets not supported!"));
 125.443 -            return null;
 125.444 -        }
 125.445 -
 125.446 -        @Override
 125.447 -        public void send(Void socket, JSONCall data) {
 125.448 -        }
 125.449 -
 125.450 -        @Override
 125.451 -        public void close(Void socket) {
 125.452 -        }
 125.453 -    }
 125.454 -    
 125.455 -}
   126.1 --- a/json/src/main/java/org/apidesign/html/json/impl/JSONList.java	Thu Dec 19 17:11:01 2013 +0100
   126.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   126.3 @@ -1,214 +0,0 @@
   126.4 -/**
   126.5 - * HTML via Java(tm) Language Bindings
   126.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   126.7 - *
   126.8 - * This program is free software: you can redistribute it and/or modify
   126.9 - * it under the terms of the GNU General Public License as published by
  126.10 - * the Free Software Foundation, version 2 of the License.
  126.11 - *
  126.12 - * This program is distributed in the hope that it will be useful,
  126.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  126.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  126.15 - * GNU General Public License for more details. apidesign.org
  126.16 - * designates this particular file as subject to the
  126.17 - * "Classpath" exception as provided by apidesign.org
  126.18 - * in the License file that accompanied this code.
  126.19 - *
  126.20 - * You should have received a copy of the GNU General Public License
  126.21 - * along with this program. Look for COPYING file in the top folder.
  126.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  126.23 - */
  126.24 -package org.apidesign.html.json.impl;
  126.25 -
  126.26 -import java.lang.reflect.Array;
  126.27 -import java.util.ArrayList;
  126.28 -import java.util.Arrays;
  126.29 -import java.util.Collection;
  126.30 -import java.util.Iterator;
  126.31 -import java.util.List;
  126.32 -import net.java.html.BrwsrCtx;
  126.33 -
  126.34 -/**
  126.35 - *
  126.36 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  126.37 - */
  126.38 -public final class JSONList<T> extends ArrayList<T> {
  126.39 -    private final String name;
  126.40 -    private final String[] deps;
  126.41 -    private Bindings[] model;
  126.42 -    private Runnable onchange;
  126.43 -
  126.44 -    public JSONList(Bindings[] model, String name, String... deps) {
  126.45 -        assert model.length == 1;
  126.46 -        this.model = model;
  126.47 -        this.name = name;
  126.48 -        this.deps = deps;
  126.49 -    }
  126.50 -    
  126.51 -    public void init(T... values) {
  126.52 -        if (values == null || values.length == 0) {
  126.53 -            return;
  126.54 -        }
  126.55 -        if (this.model[0] != null || !isEmpty()) {
  126.56 -            throw new IllegalStateException();
  126.57 -        }
  126.58 -        super.addAll(Arrays.asList(values));
  126.59 -    }
  126.60 -    
  126.61 -    public void init(Object values) {
  126.62 -        int len;
  126.63 -        if (values == null || (len = Array.getLength(values)) == 0) {
  126.64 -            return;
  126.65 -        }
  126.66 -        if (this.model[0] != null || !isEmpty()) {
  126.67 -            throw new IllegalStateException();
  126.68 -        }
  126.69 -        for (int i = 0; i < len; i++) {
  126.70 -            Object data = Array.get(values, i);
  126.71 -            super.add((T)data);
  126.72 -        }
  126.73 -    }
  126.74 -    
  126.75 -    public JSONList<T> onChange(Runnable r) {
  126.76 -        if (this.onchange != null) {
  126.77 -            throw new IllegalStateException();
  126.78 -        }
  126.79 -        this.onchange = r;
  126.80 -        return this;
  126.81 -    }
  126.82 -
  126.83 -    @Override
  126.84 -    public boolean add(T e) {
  126.85 -        boolean ret = super.add(e);
  126.86 -        notifyChange();
  126.87 -        return ret;
  126.88 -    }
  126.89 -
  126.90 -    @Override
  126.91 -    public boolean addAll(Collection<? extends T> c) {
  126.92 -        boolean ret = super.addAll(c);
  126.93 -        notifyChange();
  126.94 -        return ret;
  126.95 -    }
  126.96 -
  126.97 -    @Override
  126.98 -    public boolean addAll(int index, Collection<? extends T> c) {
  126.99 -        boolean ret = super.addAll(index, c);
 126.100 -        notifyChange();
 126.101 -        return ret;
 126.102 -    }
 126.103 -
 126.104 -    @Override
 126.105 -    public boolean remove(Object o) {
 126.106 -        boolean ret = super.remove(o);
 126.107 -        notifyChange();
 126.108 -        return ret;
 126.109 -    }
 126.110 -
 126.111 -    @Override
 126.112 -    public void clear() {
 126.113 -        super.clear();
 126.114 -        notifyChange();
 126.115 -    }
 126.116 -
 126.117 -    @Override
 126.118 -    public boolean removeAll(Collection<?> c) {
 126.119 -        boolean ret = super.removeAll(c);
 126.120 -        notifyChange();
 126.121 -        return ret;
 126.122 -    }
 126.123 -
 126.124 -    @Override
 126.125 -    public boolean retainAll(Collection<?> c) {
 126.126 -        boolean ret = super.retainAll(c);
 126.127 -        notifyChange();
 126.128 -        return ret;
 126.129 -    }
 126.130 -
 126.131 -    @Override
 126.132 -    public T set(int index, T element) {
 126.133 -        T ret = super.set(index, element);
 126.134 -        notifyChange();
 126.135 -        return ret;
 126.136 -    }
 126.137 -
 126.138 -    @Override
 126.139 -    public void add(int index, T element) {
 126.140 -        super.add(index, element);
 126.141 -        notifyChange();
 126.142 -    }
 126.143 -
 126.144 -    @Override
 126.145 -    public T remove(int index) {
 126.146 -        T ret = super.remove(index);
 126.147 -        notifyChange();
 126.148 -        return ret;
 126.149 -    }
 126.150 -
 126.151 -    @Override
 126.152 -    public String toString() {
 126.153 -        Iterator<T> it = iterator();
 126.154 -        if (!it.hasNext()) {
 126.155 -            return "[]";
 126.156 -        }
 126.157 -        String sep = "";
 126.158 -        StringBuilder sb = new StringBuilder();
 126.159 -        sb.append('[');
 126.160 -        while (it.hasNext()) {
 126.161 -            T t = it.next();
 126.162 -            sb.append(sep);
 126.163 -            sb.append(JSON.toJSON(t));
 126.164 -            sep = ",";
 126.165 -        }
 126.166 -        sb.append(']');
 126.167 -        return sb.toString();
 126.168 -    }
 126.169 -
 126.170 -    private void notifyChange() {
 126.171 -        Bindings m = model[0];
 126.172 -        if (m != null) {
 126.173 -            m.valueHasMutated(name);
 126.174 -            for (String dependant : deps) {
 126.175 -                m.valueHasMutated(dependant);
 126.176 -            }
 126.177 -            Runnable r = onchange;
 126.178 -            if (r != null) {
 126.179 -                r.run();
 126.180 -            }
 126.181 -        }
 126.182 -    }
 126.183 -    
 126.184 -    public void cloneAll(BrwsrCtx c, Collection<T> other) {
 126.185 -        Boolean isModel = null;
 126.186 -        for (T t : other) {
 126.187 -            if (isModel == null) {
 126.188 -                isModel = JSON.isModel(t.getClass());
 126.189 -            }
 126.190 -            if (isModel) {
 126.191 -                add(JSON.bindTo(t, c));
 126.192 -            } else {
 126.193 -                add(t);
 126.194 -            }
 126.195 -        }
 126.196 -    }
 126.197 -
 126.198 -    @Override
 126.199 -    public JSONList clone() {
 126.200 -        throw new UnsupportedOperationException();
 126.201 -    }
 126.202 -
 126.203 -    static final Object koData(Collection<?> c, Bindings m) {
 126.204 -        Object[] arr = c.toArray(new Object[c.size()]);
 126.205 -        for (int i = 0; i < arr.length; i++) {
 126.206 -            Object r = WrapperObject.find(arr[i], m);
 126.207 -            if (r != null) {
 126.208 -                arr[i] = r;
 126.209 -            }
 126.210 -        }
 126.211 -        return m.wrapArray(arr);
 126.212 -    }
 126.213 -
 126.214 -    final Object koData() {
 126.215 -        return koData(this, model[0]);
 126.216 -    }
 126.217 -}
   127.1 --- a/json/src/main/java/org/apidesign/html/json/impl/ModelProcessor.java	Thu Dec 19 17:11:01 2013 +0100
   127.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   127.3 @@ -1,1745 +0,0 @@
   127.4 -/**
   127.5 - * HTML via Java(tm) Language Bindings
   127.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   127.7 - *
   127.8 - * This program is free software: you can redistribute it and/or modify
   127.9 - * it under the terms of the GNU General Public License as published by
  127.10 - * the Free Software Foundation, version 2 of the License.
  127.11 - *
  127.12 - * This program is distributed in the hope that it will be useful,
  127.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  127.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  127.15 - * GNU General Public License for more details. apidesign.org
  127.16 - * designates this particular file as subject to the
  127.17 - * "Classpath" exception as provided by apidesign.org
  127.18 - * in the License file that accompanied this code.
  127.19 - *
  127.20 - * You should have received a copy of the GNU General Public License
  127.21 - * along with this program. Look for COPYING file in the top folder.
  127.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  127.23 - */
  127.24 -package org.apidesign.html.json.impl;
  127.25 -
  127.26 -import java.io.IOException;
  127.27 -import java.io.OutputStreamWriter;
  127.28 -import java.io.StringWriter;
  127.29 -import java.io.Writer;
  127.30 -import java.lang.annotation.AnnotationTypeMismatchException;
  127.31 -import java.lang.annotation.IncompleteAnnotationException;
  127.32 -import java.lang.reflect.Method;
  127.33 -import java.util.ArrayList;
  127.34 -import java.util.Arrays;
  127.35 -import java.util.Collection;
  127.36 -import java.util.Collections;
  127.37 -import java.util.HashMap;
  127.38 -import java.util.HashSet;
  127.39 -import java.util.LinkedHashSet;
  127.40 -import java.util.List;
  127.41 -import java.util.Map;
  127.42 -import java.util.ResourceBundle;
  127.43 -import java.util.Set;
  127.44 -import java.util.WeakHashMap;
  127.45 -import java.util.logging.Level;
  127.46 -import java.util.logging.Logger;
  127.47 -import javax.annotation.processing.AbstractProcessor;
  127.48 -import javax.annotation.processing.Completion;
  127.49 -import javax.annotation.processing.Completions;
  127.50 -import javax.annotation.processing.ProcessingEnvironment;
  127.51 -import javax.annotation.processing.Processor;
  127.52 -import javax.annotation.processing.RoundEnvironment;
  127.53 -import javax.annotation.processing.SupportedAnnotationTypes;
  127.54 -import javax.annotation.processing.SupportedSourceVersion;
  127.55 -import javax.lang.model.SourceVersion;
  127.56 -import javax.lang.model.element.AnnotationMirror;
  127.57 -import javax.lang.model.element.AnnotationValue;
  127.58 -import javax.lang.model.element.Element;
  127.59 -import javax.lang.model.element.ElementKind;
  127.60 -import javax.lang.model.element.ExecutableElement;
  127.61 -import javax.lang.model.element.Modifier;
  127.62 -import javax.lang.model.element.PackageElement;
  127.63 -import javax.lang.model.element.TypeElement;
  127.64 -import javax.lang.model.element.VariableElement;
  127.65 -import javax.lang.model.type.ArrayType;
  127.66 -import javax.lang.model.type.DeclaredType;
  127.67 -import javax.lang.model.type.MirroredTypeException;
  127.68 -import javax.lang.model.type.TypeKind;
  127.69 -import javax.lang.model.type.TypeMirror;
  127.70 -import javax.lang.model.util.Elements;
  127.71 -import javax.lang.model.util.Types;
  127.72 -import javax.tools.Diagnostic;
  127.73 -import javax.tools.FileObject;
  127.74 -import net.java.html.json.ComputedProperty;
  127.75 -import net.java.html.json.Model;
  127.76 -import net.java.html.json.Function;
  127.77 -import net.java.html.json.ModelOperation;
  127.78 -import net.java.html.json.OnPropertyChange;
  127.79 -import net.java.html.json.OnReceive;
  127.80 -import net.java.html.json.Property;
  127.81 -import org.openide.util.lookup.ServiceProvider;
  127.82 -
  127.83 -/** Annotation processor to process {@link Model @Model} annotations and
  127.84 - * generate appropriate model classes.
  127.85 - *
  127.86 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  127.87 - */
  127.88 -@ServiceProvider(service=Processor.class)
  127.89 -@SupportedSourceVersion(SourceVersion.RELEASE_6)
  127.90 -@SupportedAnnotationTypes({
  127.91 -    "net.java.html.json.Model",
  127.92 -    "net.java.html.json.ModelOperation",
  127.93 -    "net.java.html.json.Function",
  127.94 -    "net.java.html.json.OnReceive",
  127.95 -    "net.java.html.json.OnPropertyChange",
  127.96 -    "net.java.html.json.ComputedProperty",
  127.97 -    "net.java.html.json.Property"
  127.98 -})
  127.99 -public final class ModelProcessor extends AbstractProcessor {
 127.100 -    private static final Logger LOG = Logger.getLogger(ModelProcessor.class.getName());
 127.101 -    private final Map<Element,String> models = new WeakHashMap<Element,String>();
 127.102 -    private final Map<Element,Prprt[]> verify = new WeakHashMap<Element,Prprt[]>();
 127.103 -    @Override
 127.104 -    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
 127.105 -        boolean ok = true;
 127.106 -        for (Element e : roundEnv.getElementsAnnotatedWith(Model.class)) {
 127.107 -            if (!processModel(e)) {
 127.108 -                ok = false;
 127.109 -            }
 127.110 -        }
 127.111 -        if (roundEnv.processingOver()) {
 127.112 -            models.clear();
 127.113 -            for (Map.Entry<Element, Prprt[]> entry : verify.entrySet()) {
 127.114 -                TypeElement te = (TypeElement)entry.getKey();
 127.115 -                String fqn = processingEnv.getElementUtils().getBinaryName(te).toString();
 127.116 -                Element finalElem = processingEnv.getElementUtils().getTypeElement(fqn);
 127.117 -                if (finalElem == null) {
 127.118 -                    continue;
 127.119 -                }
 127.120 -                Prprt[] props;
 127.121 -                Model m = finalElem.getAnnotation(Model.class);
 127.122 -                if (m == null) {
 127.123 -                    continue;
 127.124 -                }
 127.125 -                props = Prprt.wrap(processingEnv, finalElem, m.properties());
 127.126 -                for (Prprt p : props) {
 127.127 -                    boolean[] isModel = { false };
 127.128 -                    boolean[] isEnum = { false };
 127.129 -                    boolean[] isPrimitive = { false };
 127.130 -                    String t = checkType(p, isModel, isEnum, isPrimitive);
 127.131 -                    if (isEnum[0]) {
 127.132 -                        continue;
 127.133 -                    }
 127.134 -                    if (isPrimitive[0]) {
 127.135 -                        continue;
 127.136 -                    }
 127.137 -                    if (isModel[0]) {
 127.138 -                        continue;
 127.139 -                    }
 127.140 -                    if ("java.lang.String".equals(t)) {
 127.141 -                        continue;
 127.142 -                    }
 127.143 -                    error("The type " + t + " should be defined by @Model annotation", entry.getKey());
 127.144 -                }
 127.145 -            }
 127.146 -            verify.clear();
 127.147 -        }
 127.148 -        return ok;
 127.149 -    }
 127.150 -
 127.151 -    private void error(String msg, Element e) {
 127.152 -        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e);
 127.153 -    }
 127.154 -    
 127.155 -    private boolean processModel(Element e) {
 127.156 -        boolean ok = true;
 127.157 -        Model m = e.getAnnotation(Model.class);
 127.158 -        if (m == null) {
 127.159 -            return true;
 127.160 -        }
 127.161 -        String pkg = findPkgName(e);
 127.162 -        Writer w;
 127.163 -        String className = m.className();
 127.164 -        models.put(e, className);
 127.165 -        try {
 127.166 -            StringWriter body = new StringWriter();
 127.167 -            List<String> propsGetSet = new ArrayList<String>();
 127.168 -            List<String> functions = new ArrayList<String>();
 127.169 -            Map<String, Collection<String>> propsDeps = new HashMap<String, Collection<String>>();
 127.170 -            Map<String, Collection<String>> functionDeps = new HashMap<String, Collection<String>>();
 127.171 -            Prprt[] props = createProps(e, m.properties());
 127.172 -            
 127.173 -            if (!generateComputedProperties(body, props, e.getEnclosedElements(), propsGetSet, propsDeps)) {
 127.174 -                ok = false;
 127.175 -            }
 127.176 -            if (!generateOnChange(e, propsDeps, props, className, functionDeps)) {
 127.177 -                ok = false;
 127.178 -            }
 127.179 -            if (!generateProperties(e, body, props, propsGetSet, propsDeps, functionDeps)) {
 127.180 -                ok = false;
 127.181 -            }
 127.182 -            if (!generateFunctions(e, body, className, e.getEnclosedElements(), functions)) {
 127.183 -                ok = false;
 127.184 -            }
 127.185 -            if (!generateReceive(e, body, className, e.getEnclosedElements(), functions)) {
 127.186 -                ok = false;
 127.187 -            }
 127.188 -            if (!generateOperation(e, body, className, e.getEnclosedElements())) {
 127.189 -                ok = false;
 127.190 -            }
 127.191 -            FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
 127.192 -            w = new OutputStreamWriter(java.openOutputStream());
 127.193 -            try {
 127.194 -                w.append("package " + pkg + ";\n");
 127.195 -                w.append("import net.java.html.json.*;\n");
 127.196 -                w.append("public final class ").append(className).append(" implements Cloneable {\n");
 127.197 -                w.append("  private boolean locked;\n");
 127.198 -                w.append("  private net.java.html.BrwsrCtx context;\n");
 127.199 -                w.append("  private org.apidesign.html.json.impl.Bindings[] ko = { null };\n");
 127.200 -                w.append(body.toString());
 127.201 -                w.append("  private static Class<" + inPckName(e) + "> modelFor() { return null; }\n");
 127.202 -                w.append("  private ").append(className).append("(net.java.html.BrwsrCtx context) {\n");
 127.203 -                w.append("    this.context = context;\n");
 127.204 -                w.append("  };\n");
 127.205 -                w.append("  public ").append(className).append("() {\n");
 127.206 -                w.append("    this(net.java.html.BrwsrCtx.findDefault(").append(className).append(".class));\n");
 127.207 -                for (Prprt p : props) {
 127.208 -                    if (p.array()) {
 127.209 -                        continue;
 127.210 -                    }
 127.211 -                    boolean[] isModel = {false};
 127.212 -                    boolean[] isEnum = {false};
 127.213 -                    boolean isPrimitive[] = {false};
 127.214 -                    String tn = checkType(p, isModel, isEnum, isPrimitive);
 127.215 -                    if (isModel[0]) {
 127.216 -                        w.write("    prop_" + p.name() + " = new " + tn + "();\n");
 127.217 -                    }
 127.218 -                }
 127.219 -                w.append("  };\n");
 127.220 -                if (props.length > 0) {
 127.221 -                    w.append("  public ").append(className).append("(");
 127.222 -                    Prprt firstArray = null;
 127.223 -                    String sep = "";
 127.224 -                    for (Prprt p : props) {
 127.225 -                        if (p.array()) {
 127.226 -                            if (firstArray == null) {
 127.227 -                                firstArray = p;
 127.228 -                            }
 127.229 -                            continue;
 127.230 -                        }
 127.231 -                        String tn = typeName(e, p);
 127.232 -                        w.write(sep);
 127.233 -                        w.write(tn);
 127.234 -                        w.write(" " + p.name());
 127.235 -                        sep = ", ";
 127.236 -                    }
 127.237 -                    if (firstArray != null) {
 127.238 -                        String tn;
 127.239 -                        boolean[] isModel = {false};
 127.240 -                        boolean[] isEnum = {false};
 127.241 -                        boolean isPrimitive[] = {false};
 127.242 -                        tn = checkType(firstArray, isModel, isEnum, isPrimitive);
 127.243 -                        w.write(sep);
 127.244 -                        w.write(tn);
 127.245 -                        w.write("... " + firstArray.name());
 127.246 -                    }
 127.247 -                    w.append(") {\n");
 127.248 -                    w.append("    this(net.java.html.BrwsrCtx.findDefault(").append(className).append(".class));\n");
 127.249 -                    for (Prprt p : props) {
 127.250 -                        if (p.array()) {
 127.251 -                            continue;
 127.252 -                        }
 127.253 -                        w.write("    this.prop_" + p.name() + " = " + p.name() + ";\n");
 127.254 -                    }
 127.255 -                    if (firstArray != null) {
 127.256 -                        w.write("    this.prop_" + firstArray.name() + ".init(" + firstArray.name() + ");\n");
 127.257 -                    }
 127.258 -                    w.append("  };\n");
 127.259 -                }
 127.260 -                w.append("  private org.apidesign.html.json.impl.Bindings intKnckt() {\n");
 127.261 -                w.append("    if (ko[0] != null) return ko[0];\n");
 127.262 -                w.append("    ko[0] = org.apidesign.html.json.impl.Bindings.apply(context, this);\n");
 127.263 -                {
 127.264 -                    w.append("    org.apidesign.html.json.spi.PropertyBinding[] propArr = {\n");
 127.265 -                    for (int i = 0; i < propsGetSet.size(); i += 5) {
 127.266 -                        w.append("      ko[0].registerProperty(\"").append(propsGetSet.get(i)).append("\", this, new P(");
 127.267 -                        w.append((i / 5) + "), " + (propsGetSet.get(i + 2) == null) + "),\n");
 127.268 -                    }
 127.269 -                    w.append("    };\n");
 127.270 -                }
 127.271 -                {
 127.272 -                    w.append("    org.apidesign.html.json.spi.FunctionBinding[] funcArr = {\n");
 127.273 -                    for (int i = 0; i < functions.size(); i += 2) {
 127.274 -                        w.append("      ko[0].registerFunction(\"").append(functions.get(i)).append("\", this, new P(");
 127.275 -                        w.append((i / 2) + ")),\n");
 127.276 -                    }
 127.277 -                    w.append("    };\n");
 127.278 -                }
 127.279 -                w.append("    ko[0].finish(this, propArr, funcArr);\n");
 127.280 -                w.append("    return ko[0];\n");
 127.281 -                w.append("  };\n");
 127.282 -                w.append("  private static final class P implements org.apidesign.html.json.impl.SetAndGet<" + className + ">,\n");
 127.283 -                w.append("  org.apidesign.html.json.impl.Callback<" + className + ">,\n");
 127.284 -                w.append("  org.apidesign.html.json.impl.FromJSON<" + className + "> {\n");
 127.285 -                w.append("    private final int type;\n");
 127.286 -                w.append("    P(int t) { type = t; };\n");
 127.287 -                w.append("    public void setValue(" + className + " data, Object value) {\n");
 127.288 -                w.append("      switch (type) {\n");
 127.289 -                for (int i = 0; i < propsGetSet.size(); i += 5) {
 127.290 -                    final String set = propsGetSet.get(i + 2);
 127.291 -                    String tn = propsGetSet.get(i + 4);
 127.292 -                    String btn = findBoxedType(tn);
 127.293 -                    if (btn != null) {
 127.294 -                        tn = btn;
 127.295 -                    }
 127.296 -                    if (set != null) {
 127.297 -                        w.append("        case " + (i / 5) + ": data." + strip(set) + "(org.apidesign.html.json.impl.JSON.extractValue(" + tn + ".class, value)); return;\n");
 127.298 -                    }
 127.299 -                }
 127.300 -                w.append("      }\n");
 127.301 -                w.append("    }\n");
 127.302 -                w.append("    public Object getValue(" + className + " data) {\n");
 127.303 -                w.append("      switch (type) {\n");
 127.304 -                for (int i = 0; i < propsGetSet.size(); i += 5) {
 127.305 -                    final String get = propsGetSet.get(i + 1);
 127.306 -                    if (get != null) {
 127.307 -                        w.append("        case " + (i / 5) + ": return data." + strip(get) + "();\n");
 127.308 -                    }
 127.309 -                }
 127.310 -                w.append("      }\n");
 127.311 -                w.append("      throw new UnsupportedOperationException();\n");
 127.312 -                w.append("    }\n");
 127.313 -                w.append("    public void call(" + className + " model, Object data, Object ev) {\n");
 127.314 -                w.append("      switch (type) {\n");
 127.315 -                for (int i = 0; i < functions.size(); i += 2) {
 127.316 -                    final String name = functions.get(i);
 127.317 -                    w.append("        case " + (i / 2) + ": model." + name + "(data, ev); return;\n");
 127.318 -                }
 127.319 -                w.append("      }\n");
 127.320 -                w.append("      throw new UnsupportedOperationException();\n");
 127.321 -                w.append("    }\n");
 127.322 -                w.append("    public Class<" + className + "> factoryFor() { return " + className + ".class; }\n");
 127.323 -                w.append("    public " + className + " read(net.java.html.BrwsrCtx c, Object json) { return new " + className + "(c, json); }\n");
 127.324 -                w.append("    public " + className + " cloneTo(Object o, net.java.html.BrwsrCtx c) { return ((" + className + ")o).clone(c); }\n");
 127.325 -                w.append("  }\n");
 127.326 -                w.append("  static { org.apidesign.html.json.impl.JSON.register(new P(0)); }\n");
 127.327 -                w.append("  private ").append(className).append("(net.java.html.BrwsrCtx c, Object json) {\n");
 127.328 -                w.append("    this.context = c;\n");
 127.329 -                int values = 0;
 127.330 -                for (int i = 0; i < propsGetSet.size(); i += 5) {
 127.331 -                    Prprt p = findPrprt(props, propsGetSet.get(i));
 127.332 -                    if (p == null) {
 127.333 -                        continue;
 127.334 -                    }
 127.335 -                    values++;
 127.336 -                }
 127.337 -                w.append("    Object[] ret = new Object[" + values + "];\n");
 127.338 -                w.append("    org.apidesign.html.json.impl.JSON.extract(context, json, new String[] {\n");
 127.339 -                for (int i = 0; i < propsGetSet.size(); i += 5) {
 127.340 -                    Prprt p = findPrprt(props, propsGetSet.get(i));
 127.341 -                    if (p == null) {
 127.342 -                        continue;
 127.343 -                    }
 127.344 -                    w.append("      \"").append(propsGetSet.get(i)).append("\",\n");
 127.345 -                }
 127.346 -                w.append("    }, ret);\n");
 127.347 -                for (int i = 0, cnt = 0, prop = 0; i < propsGetSet.size(); i += 5) {
 127.348 -                    final String pn = propsGetSet.get(i);
 127.349 -                    Prprt p = findPrprt(props, pn);
 127.350 -                    if (p == null) {
 127.351 -                        continue;
 127.352 -                    }
 127.353 -                    boolean[] isModel = { false };
 127.354 -                    boolean[] isEnum = { false };
 127.355 -                    boolean isPrimitive[] = { false };
 127.356 -                    String type = checkType(props[prop++], isModel, isEnum, isPrimitive);
 127.357 -                    if (p.array()) {
 127.358 -                        w.append("    if (ret[" + cnt + "] instanceof Object[]) {\n");
 127.359 -                        w.append("      for (Object e : ((Object[])ret[" + cnt + "])) {\n");
 127.360 -                        if (isModel[0]) {
 127.361 -                            w.append("        this.prop_").append(pn).append(".add(org.apidesign.html.json.impl.JSON.read");
 127.362 -                            w.append("(c, " + type + ".class, e));\n");
 127.363 -                        } else if (isEnum[0]) {
 127.364 -                            w.append("        this.prop_").append(pn);
 127.365 -                            w.append(".add(e == null ? null : ");
 127.366 -                            w.append(type).append(".valueOf(org.apidesign.html.json.impl.JSON.stringValue(e)));\n");
 127.367 -                        } else {
 127.368 -                            if (isPrimitive(type)) {
 127.369 -                                w.append("        this.prop_").append(pn).append(".add(org.apidesign.html.json.impl.JSON.numberValue(e).");
 127.370 -                                w.append(type).append("Value());\n");
 127.371 -                            } else {
 127.372 -                                w.append("        this.prop_").append(pn).append(".add((");
 127.373 -                                w.append(type).append(")e);\n");
 127.374 -                            }
 127.375 -                        }
 127.376 -                        w.append("      }\n");
 127.377 -                        w.append("    }\n");
 127.378 -                    } else {
 127.379 -                        if (isEnum[0]) {
 127.380 -                            w.append("    try {\n");
 127.381 -                            w.append("    this.prop_").append(pn);
 127.382 -                            w.append(" = ret[" + cnt + "] == null ? null : ");
 127.383 -                            w.append(type).append(".valueOf(org.apidesign.html.json.impl.JSON.stringValue(ret[" + cnt + "]));\n");
 127.384 -                            w.append("    } catch (IllegalArgumentException ex) {\n");
 127.385 -                            w.append("      ex.printStackTrace();\n");
 127.386 -                            w.append("    }\n");
 127.387 -                        } else if (isPrimitive(type)) {
 127.388 -                            w.append("    this.prop_").append(pn);
 127.389 -                            w.append(" = ret[" + cnt + "] == null ? ");
 127.390 -                            if ("char".equals(type)) {
 127.391 -                                w.append("0 : (org.apidesign.html.json.impl.JSON.charValue(");
 127.392 -                            } else if ("boolean".equals(type)) {
 127.393 -                                w.append("false : (org.apidesign.html.json.impl.JSON.boolValue(");
 127.394 -                            } else {
 127.395 -                                w.append("0 : (org.apidesign.html.json.impl.JSON.numberValue(");
 127.396 -                            }
 127.397 -                            w.append("ret[" + cnt + "])).");
 127.398 -                            w.append(type).append("Value();\n");
 127.399 -                        } else if (isModel[0]) {
 127.400 -                            w.append("    this.prop_").append(pn).append(" = org.apidesign.html.json.impl.JSON.read");
 127.401 -                            w.append("(c, " + type + ".class, ");
 127.402 -                            w.append("ret[" + cnt + "]);\n");
 127.403 -                        }else {
 127.404 -                            w.append("    this.prop_").append(pn);
 127.405 -                            w.append(" = (").append(type).append(')');
 127.406 -                            w.append("ret[" + cnt + "];\n");
 127.407 -                        }
 127.408 -                    }
 127.409 -                    cnt++;
 127.410 -                }
 127.411 -                w.append("  };\n");
 127.412 -                writeToString(props, w);
 127.413 -                writeClone(className, props, w);
 127.414 -                w.write("  /** Activates this model instance in the current {@link \n"
 127.415 -                    + "net.java.html.json.Models#bind(java.lang.Object, net.java.html.BrwsrCtx) browser context}. \n"
 127.416 -                    + "In case of using Knockout technology, this means to \n"
 127.417 -                    + "bind JSON like data in this model instance with Knockout tags in \n"
 127.418 -                    + "the surrounding HTML page.\n"
 127.419 -                    + "*/\n"
 127.420 -                );
 127.421 -                w.write("  public " + className + " applyBindings() {\n");
 127.422 -                w.write("    intKnckt().applyBindings();\n");
 127.423 -                w.write("    return this;\n");
 127.424 -                w.write("  }\n");
 127.425 -                w.write("  public boolean equals(Object o) {\n");
 127.426 -                w.write("    if (o == this) return true;\n");
 127.427 -                w.write("    if (o instanceof org.apidesign.html.json.impl.WrapperObject) {\n");
 127.428 -                w.write("      ((org.apidesign.html.json.impl.WrapperObject)o).setRealObject(intKnckt().koData());\n");
 127.429 -                w.write("      return false;\n");
 127.430 -                w.write("    }\n");
 127.431 -                w.write("    if (!(o instanceof " + className + ")) return false;\n");
 127.432 -                w.write("    " + className + " p = (" + className + ")o;\n");
 127.433 -                for (Prprt p : props) {
 127.434 -                    w.write("    if (!org.apidesign.html.json.impl.JSON.isSame(prop_" + p.name() + ", p.prop_" + p.name() + ")) return false;\n");
 127.435 -                }
 127.436 -                w.write("    return true;\n");
 127.437 -                w.write("  }\n");
 127.438 -                w.write("  public int hashCode() {\n");
 127.439 -                w.write("    int h = " + className + ".class.getName().hashCode();\n");
 127.440 -                for (Prprt p : props) {
 127.441 -                    w.write("    h = org.apidesign.html.json.impl.JSON.hashPlus(prop_" + p.name() + ", h);\n");
 127.442 -                }
 127.443 -                w.write("    return h;\n");
 127.444 -                w.write("  }\n");
 127.445 -                w.write("}\n");
 127.446 -            } finally {
 127.447 -                w.close();
 127.448 -            }
 127.449 -        } catch (IOException ex) {
 127.450 -            error("Can't create " + className + ".java", e);
 127.451 -            return false;
 127.452 -        }
 127.453 -        return ok;
 127.454 -    }
 127.455 -    
 127.456 -    private boolean generateProperties(
 127.457 -        Element where,
 127.458 -        Writer w, Prprt[] properties,
 127.459 -        Collection<String> props, 
 127.460 -        Map<String,Collection<String>> deps,
 127.461 -        Map<String,Collection<String>> functionDeps
 127.462 -    ) throws IOException {
 127.463 -        boolean ok = true;
 127.464 -        for (Prprt p : properties) {
 127.465 -            final String tn;
 127.466 -            tn = typeName(where, p);
 127.467 -            String[] gs = toGetSet(p.name(), tn, p.array());
 127.468 -            String castTo;
 127.469 -            
 127.470 -            if (p.array()) {
 127.471 -                w.write("  private org.apidesign.html.json.impl.JSONList<" + tn + "> prop_" + p.name() + " = new org.apidesign.html.json.impl.JSONList<" + tn + ">(ko, \""
 127.472 -                    + p.name() + "\"");
 127.473 -                Collection<String> dependants = deps.get(p.name());
 127.474 -                if (dependants != null) {
 127.475 -                    for (String depProp : dependants) {
 127.476 -                        w.write(", ");
 127.477 -                        w.write('\"');
 127.478 -                        w.write(depProp);
 127.479 -                        w.write('\"');
 127.480 -                    }
 127.481 -                }
 127.482 -                w.write(")");
 127.483 -                
 127.484 -                dependants = functionDeps.get(p.name());
 127.485 -                if (dependants != null) {
 127.486 -                    w.write(".onChange(new Runnable() { public void run() {\n");
 127.487 -                    for (String call : dependants) {
 127.488 -                        w.append("  ").append(call);
 127.489 -                    }
 127.490 -                    w.write("  }})");
 127.491 -                }
 127.492 -                w.write(";\n");
 127.493 -            
 127.494 -                castTo = "java.util.List";
 127.495 -                w.write("  public java.util.List<" + tn + "> " + gs[0] + "() {\n");
 127.496 -                w.write("    if (locked) throw new IllegalStateException();\n");
 127.497 -                w.write("    return prop_" + p.name() + ";\n");
 127.498 -                w.write("  }\n");
 127.499 -            } else {
 127.500 -                castTo = tn;
 127.501 -                w.write("  private " + tn + " prop_" + p.name() + ";\n");
 127.502 -                w.write("  public " + tn + " " + gs[0] + "() {\n");
 127.503 -                w.write("    if (locked) throw new IllegalStateException();\n");
 127.504 -                w.write("    return prop_" + p.name() + ";\n");
 127.505 -                w.write("  }\n");
 127.506 -                w.write("  public void " + gs[1] + "(" + tn + " v) {\n");
 127.507 -                w.write("    if (locked) throw new IllegalStateException();\n");
 127.508 -                w.write("    if (org.apidesign.html.json.impl.JSON.isSame(prop_" + p.name() + ", v)) return;\n");
 127.509 -                w.write("    prop_" + p.name() + " = v;\n");
 127.510 -                w.write("    org.apidesign.html.json.impl.Bindings b = ko[0];\n");
 127.511 -                w.write("    if (b != null) {\n");
 127.512 -                w.write("      b.valueHasMutated(\"" + p.name() + "\");\n");
 127.513 -                Collection<String> dependants = deps.get(p.name());
 127.514 -                if (dependants != null) {
 127.515 -                    for (String depProp : dependants) {
 127.516 -                        w.write("      b.valueHasMutated(\"" + depProp + "\");\n");
 127.517 -                    }
 127.518 -                }
 127.519 -                w.write("    }\n");
 127.520 -                dependants = functionDeps.get(p.name());
 127.521 -                if (dependants != null) {
 127.522 -                    for (String call : dependants) {
 127.523 -                        w.append("  ").append(call);
 127.524 -                    }
 127.525 -                }
 127.526 -                w.write("  }\n");
 127.527 -            }
 127.528 -            
 127.529 -            props.add(p.name());
 127.530 -            props.add(gs[2]);
 127.531 -            props.add(gs[3]);
 127.532 -            props.add(gs[0]);
 127.533 -            props.add(castTo);
 127.534 -        }
 127.535 -        return ok;
 127.536 -    }
 127.537 -
 127.538 -    private boolean generateComputedProperties(
 127.539 -        Writer w, Prprt[] fixedProps,
 127.540 -        Collection<? extends Element> arr, Collection<String> props,
 127.541 -        Map<String,Collection<String>> deps
 127.542 -    ) throws IOException {
 127.543 -        boolean ok = true;
 127.544 -        for (Element e : arr) {
 127.545 -            if (e.getKind() != ElementKind.METHOD) {
 127.546 -                continue;
 127.547 -            }
 127.548 -            if (e.getAnnotation(ComputedProperty.class) == null) {
 127.549 -                continue;
 127.550 -            }
 127.551 -            if (!e.getModifiers().contains(Modifier.STATIC)) {
 127.552 -                error("Method " + e.getSimpleName() + " has to be static when annotated by @ComputedProperty", e);
 127.553 -                ok = false;
 127.554 -                continue;
 127.555 -            }
 127.556 -            ExecutableElement ee = (ExecutableElement)e;
 127.557 -            final TypeMirror rt = ee.getReturnType();
 127.558 -            final Types tu = processingEnv.getTypeUtils();
 127.559 -            TypeMirror ert = tu.erasure(rt);
 127.560 -            String tn = fqn(ert, ee);
 127.561 -            boolean array = false;
 127.562 -            final TypeMirror toCheck;
 127.563 -            if (tn.equals("java.util.List")) {
 127.564 -                array = true;
 127.565 -                toCheck = ((DeclaredType)rt).getTypeArguments().get(0);
 127.566 -            } else {
 127.567 -                toCheck = rt;
 127.568 -            }
 127.569 -            
 127.570 -            final String sn = ee.getSimpleName().toString();
 127.571 -            
 127.572 -            if (toCheck.getKind().isPrimitive()) {
 127.573 -                // OK
 127.574 -            } else {
 127.575 -                TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
 127.576 -                TypeMirror enumType = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType();
 127.577 -
 127.578 -                if (tu.isSubtype(toCheck, stringType)) {
 127.579 -                    // OK
 127.580 -                } else if (tu.isSubtype(tu.erasure(toCheck), tu.erasure(enumType))) {
 127.581 -                    // OK
 127.582 -                } else if (isModel(toCheck)) {
 127.583 -                    // OK
 127.584 -                } else {
 127.585 -                    ok = false;
 127.586 -                    error(sn + " cannot return " + toCheck, e);
 127.587 -                }
 127.588 -            }
 127.589 -            
 127.590 -            String[] gs = toGetSet(sn, tn, array);
 127.591 -            
 127.592 -            w.write("  public " + tn + " " + gs[0] + "() {\n");
 127.593 -            w.write("    if (locked) throw new IllegalStateException();\n");
 127.594 -            int arg = 0;
 127.595 -            for (VariableElement pe : ee.getParameters()) {
 127.596 -                final String dn = pe.getSimpleName().toString();
 127.597 -                
 127.598 -                if (!verifyPropName(pe, dn, fixedProps)) {
 127.599 -                    ok = false;
 127.600 -                }
 127.601 -                
 127.602 -                final String dt = fqn(pe.asType(), ee);
 127.603 -                String[] call = toGetSet(dn, dt, false);
 127.604 -                w.write("    " + dt + " arg" + (++arg) + " = ");
 127.605 -                w.write(call[0] + "();\n");
 127.606 -                
 127.607 -                Collection<String> depends = deps.get(dn);
 127.608 -                if (depends == null) {
 127.609 -                    depends = new LinkedHashSet<String>();
 127.610 -                    deps.put(dn, depends);
 127.611 -                }
 127.612 -                depends.add(sn);
 127.613 -            }
 127.614 -            w.write("    try {\n");
 127.615 -            w.write("      locked = true;\n");
 127.616 -            w.write("      return " + fqn(ee.getEnclosingElement().asType(), ee) + '.' + e.getSimpleName() + "(");
 127.617 -            String sep = "";
 127.618 -            for (int i = 1; i <= arg; i++) {
 127.619 -                w.write(sep);
 127.620 -                w.write("arg" + i);
 127.621 -                sep = ", ";
 127.622 -            }
 127.623 -            w.write(");\n");
 127.624 -            w.write("    } finally {\n");
 127.625 -            w.write("      locked = false;\n");
 127.626 -            w.write("    }\n");
 127.627 -            w.write("  }\n");
 127.628 -
 127.629 -            props.add(e.getSimpleName().toString());
 127.630 -            props.add(gs[2]);
 127.631 -            props.add(null);
 127.632 -            props.add(gs[0]);
 127.633 -            props.add(tn);
 127.634 -        }
 127.635 -        
 127.636 -        return ok;
 127.637 -    }
 127.638 -
 127.639 -    private static String[] toGetSet(String name, String type, boolean array) {
 127.640 -        String n = Character.toUpperCase(name.charAt(0)) + name.substring(1);
 127.641 -        String bck2brwsrType = "L" + type.replace('.', '_') + "_2";
 127.642 -        if ("int".equals(type)) {
 127.643 -            bck2brwsrType = "I";
 127.644 -        }
 127.645 -        if ("double".equals(type)) {
 127.646 -            bck2brwsrType = "D";
 127.647 -        }
 127.648 -        String pref = "get";
 127.649 -        if ("boolean".equals(type)) {
 127.650 -            pref = "is";
 127.651 -            bck2brwsrType = "Z";
 127.652 -        }
 127.653 -        final String nu = n.replace('.', '_');
 127.654 -        if (array) {
 127.655 -            return new String[] { 
 127.656 -                "get" + n,
 127.657 -                null,
 127.658 -                "get" + nu + "__Ljava_util_List_2",
 127.659 -                null
 127.660 -            };
 127.661 -        }
 127.662 -        return new String[]{
 127.663 -            pref + n, 
 127.664 -            "set" + n, 
 127.665 -            pref + nu + "__" + bck2brwsrType,
 127.666 -            "set" + nu + "__V" + bck2brwsrType
 127.667 -        };
 127.668 -    }
 127.669 -
 127.670 -    private String typeName(Element where, Prprt p) {
 127.671 -        String ret;
 127.672 -        boolean[] isModel = { false };
 127.673 -        boolean[] isEnum = { false };
 127.674 -        boolean isPrimitive[] = { false };
 127.675 -        ret = checkType(p, isModel, isEnum, isPrimitive);
 127.676 -        if (p.array()) {
 127.677 -            String bt = findBoxedType(ret);
 127.678 -            if (bt != null) {
 127.679 -                return bt;
 127.680 -            }
 127.681 -        }
 127.682 -        return ret;
 127.683 -    }
 127.684 -    
 127.685 -    private static String findBoxedType(String ret) {
 127.686 -        if (ret.equals("boolean")) {
 127.687 -            return Boolean.class.getName();
 127.688 -        }
 127.689 -        if (ret.equals("byte")) {
 127.690 -            return Byte.class.getName();
 127.691 -        }
 127.692 -        if (ret.equals("short")) {
 127.693 -            return Short.class.getName();
 127.694 -        }
 127.695 -        if (ret.equals("char")) {
 127.696 -            return Character.class.getName();
 127.697 -        }
 127.698 -        if (ret.equals("int")) {
 127.699 -            return Integer.class.getName();
 127.700 -        }
 127.701 -        if (ret.equals("long")) {
 127.702 -            return Long.class.getName();
 127.703 -        }
 127.704 -        if (ret.equals("float")) {
 127.705 -            return Float.class.getName();
 127.706 -        }
 127.707 -        if (ret.equals("double")) {
 127.708 -            return Double.class.getName();
 127.709 -        }
 127.710 -        return null;
 127.711 -    }
 127.712 -
 127.713 -    private boolean verifyPropName(Element e, String propName, Prprt[] existingProps) {
 127.714 -        StringBuilder sb = new StringBuilder();
 127.715 -        String sep = "";
 127.716 -        for (Prprt Prprt : existingProps) {
 127.717 -            if (Prprt.name().equals(propName)) {
 127.718 -                return true;
 127.719 -            }
 127.720 -            sb.append(sep);
 127.721 -            sb.append('"');
 127.722 -            sb.append(Prprt.name());
 127.723 -            sb.append('"');
 127.724 -            sep = ", ";
 127.725 -        }
 127.726 -        error(
 127.727 -            propName + " is not one of known properties: " + sb
 127.728 -            , e
 127.729 -        );
 127.730 -        return false;
 127.731 -    }
 127.732 -
 127.733 -    private static String findPkgName(Element e) {
 127.734 -        for (;;) {
 127.735 -            if (e.getKind() == ElementKind.PACKAGE) {
 127.736 -                return ((PackageElement)e).getQualifiedName().toString();
 127.737 -            }
 127.738 -            e = e.getEnclosingElement();
 127.739 -        }
 127.740 -    }
 127.741 -
 127.742 -    private boolean generateFunctions(
 127.743 -        Element clazz, StringWriter body, String className, 
 127.744 -        List<? extends Element> enclosedElements, List<String> functions
 127.745 -    ) {
 127.746 -        for (Element m : enclosedElements) {
 127.747 -            if (m.getKind() != ElementKind.METHOD) {
 127.748 -                continue;
 127.749 -            }
 127.750 -            ExecutableElement e = (ExecutableElement)m;
 127.751 -            Function onF = e.getAnnotation(Function.class);
 127.752 -            if (onF == null) {
 127.753 -                continue;
 127.754 -            }
 127.755 -            if (!e.getModifiers().contains(Modifier.STATIC)) {
 127.756 -                error("@OnFunction method needs to be static", e);
 127.757 -                return false;
 127.758 -            }
 127.759 -            if (e.getModifiers().contains(Modifier.PRIVATE)) {
 127.760 -                error("@OnFunction method cannot be private", e);
 127.761 -                return false;
 127.762 -            }
 127.763 -            if (e.getReturnType().getKind() != TypeKind.VOID) {
 127.764 -                error("@OnFunction method should return void", e);
 127.765 -                return false;
 127.766 -            }
 127.767 -            String n = e.getSimpleName().toString();
 127.768 -            body.append("  private void ").append(n).append("(Object data, Object ev) {\n");
 127.769 -            body.append("    ").append(((TypeElement)clazz).getQualifiedName()).append(".").append(n).append("(");
 127.770 -            body.append(wrapParams(e, null, className, "ev", "data"));
 127.771 -            body.append(");\n");
 127.772 -            body.append("  }\n");
 127.773 -            
 127.774 -            functions.add(n);
 127.775 -            functions.add(n + "__VLjava_lang_Object_2Ljava_lang_Object_2");
 127.776 -        }
 127.777 -        return true;
 127.778 -    }
 127.779 -
 127.780 -    private boolean generateOnChange(Element clazz, Map<String,Collection<String>> propDeps,
 127.781 -        Prprt[] properties, String className, 
 127.782 -        Map<String, Collection<String>> functionDeps
 127.783 -    ) {
 127.784 -        for (Element m : clazz.getEnclosedElements()) {
 127.785 -            if (m.getKind() != ElementKind.METHOD) {
 127.786 -                continue;
 127.787 -            }
 127.788 -            ExecutableElement e = (ExecutableElement) m;
 127.789 -            OnPropertyChange onPC = e.getAnnotation(OnPropertyChange.class);
 127.790 -            if (onPC == null) {
 127.791 -                continue;
 127.792 -            }
 127.793 -            for (String pn : onPC.value()) {
 127.794 -                if (findPrprt(properties, pn) == null && findDerivedFrom(propDeps, pn).isEmpty()) {
 127.795 -                    error("No Prprt named '" + pn + "' in the model", clazz);
 127.796 -                    return false;
 127.797 -                }
 127.798 -            }
 127.799 -            if (!e.getModifiers().contains(Modifier.STATIC)) {
 127.800 -                error("@OnPrprtChange method needs to be static", e);
 127.801 -                return false;
 127.802 -            }
 127.803 -            if (e.getModifiers().contains(Modifier.PRIVATE)) {
 127.804 -                error("@OnPrprtChange method cannot be private", e);
 127.805 -                return false;
 127.806 -            }
 127.807 -            if (e.getReturnType().getKind() != TypeKind.VOID) {
 127.808 -                error("@OnPrprtChange method should return void", e);
 127.809 -                return false;
 127.810 -            }
 127.811 -            String n = e.getSimpleName().toString();
 127.812 -            
 127.813 -            
 127.814 -            for (String pn : onPC.value()) {
 127.815 -                StringBuilder call = new StringBuilder();
 127.816 -                call.append("  ").append(clazz.getSimpleName()).append(".").append(n).append("(");
 127.817 -                call.append(wrapPropName(e, className, "name", pn));
 127.818 -                call.append(");\n");
 127.819 -                
 127.820 -                Collection<String> change = functionDeps.get(pn);
 127.821 -                if (change == null) {
 127.822 -                    change = new ArrayList<String>();
 127.823 -                    functionDeps.put(pn, change);
 127.824 -                }
 127.825 -                change.add(call.toString());
 127.826 -                for (String dpn : findDerivedFrom(propDeps, pn)) {
 127.827 -                    change = functionDeps.get(dpn);
 127.828 -                    if (change == null) {
 127.829 -                        change = new ArrayList<String>();
 127.830 -                        functionDeps.put(dpn, change);
 127.831 -                    }
 127.832 -                    change.add(call.toString());
 127.833 -                }
 127.834 -            }
 127.835 -        }
 127.836 -        return true;
 127.837 -    }
 127.838 -
 127.839 -    private boolean generateOperation(Element clazz, 
 127.840 -        StringWriter body, String className, 
 127.841 -        List<? extends Element> enclosedElements
 127.842 -    ) {
 127.843 -        for (Element m : enclosedElements) {
 127.844 -            if (m.getKind() != ElementKind.METHOD) {
 127.845 -                continue;
 127.846 -            }
 127.847 -            ExecutableElement e = (ExecutableElement)m;
 127.848 -            ModelOperation mO = e.getAnnotation(ModelOperation.class);
 127.849 -            if (mO == null) {
 127.850 -                continue;
 127.851 -            }
 127.852 -            if (!e.getModifiers().contains(Modifier.STATIC)) {
 127.853 -                error("@ModelOperation method needs to be static", e);
 127.854 -                return false;
 127.855 -            }
 127.856 -            if (e.getModifiers().contains(Modifier.PRIVATE)) {
 127.857 -                error("@ModelOperation method cannot be private", e);
 127.858 -                return false;
 127.859 -            }
 127.860 -            if (e.getReturnType().getKind() != TypeKind.VOID) {
 127.861 -                error("@ModelOperation method should return void", e);
 127.862 -                return false;
 127.863 -            }
 127.864 -            List<String> args = new ArrayList<String>();
 127.865 -            {
 127.866 -                body.append("  public void ").append(m.getSimpleName()).append("(");
 127.867 -                String sep = "";
 127.868 -                boolean checkFirst = true;
 127.869 -                for (VariableElement ve : e.getParameters()) {
 127.870 -                    final TypeMirror type = ve.asType();
 127.871 -                    CharSequence simpleName;
 127.872 -                    if (type.getKind() == TypeKind.DECLARED) {
 127.873 -                        simpleName = ((DeclaredType)type).asElement().getSimpleName();
 127.874 -                    } else {
 127.875 -                        simpleName = type.toString();
 127.876 -                    }
 127.877 -                    if (simpleName.toString().equals(className)) {
 127.878 -                        checkFirst = false;
 127.879 -                    } else {
 127.880 -                        if (checkFirst) {
 127.881 -                            error("First parameter of @ModelOperation method must be " + className, m);
 127.882 -                            return false;
 127.883 -                        }
 127.884 -                        args.add(ve.getSimpleName().toString());
 127.885 -                        body.append(sep).append("final ");
 127.886 -                        body.append(ve.asType().toString()).append(" ");
 127.887 -                        body.append(ve.toString());
 127.888 -                        sep = ", ";
 127.889 -                    }
 127.890 -                }
 127.891 -                body.append(") {\n");
 127.892 -                body.append("    org.apidesign.html.json.impl.JSON.runInBrowser(this.context, new Runnable() { public void run() {\n");
 127.893 -                body.append("      ").append(clazz.getSimpleName()).append(".").append(m.getSimpleName()).append("(");
 127.894 -                body.append(className).append(".this");
 127.895 -                for (String s : args) {
 127.896 -                    body.append(", ").append(s);
 127.897 -                }
 127.898 -                body.append(");\n");
 127.899 -                body.append("    }});\n");
 127.900 -                body.append("  }\n");
 127.901 -            }
 127.902 -            
 127.903 -        }
 127.904 -        return true;
 127.905 -    }
 127.906 -    
 127.907 -    
 127.908 -    private boolean generateReceive(
 127.909 -        Element clazz, StringWriter body, String className, 
 127.910 -        List<? extends Element> enclosedElements, List<String> functions
 127.911 -    ) {
 127.912 -        for (Element m : enclosedElements) {
 127.913 -            if (m.getKind() != ElementKind.METHOD) {
 127.914 -                continue;
 127.915 -            }
 127.916 -            ExecutableElement e = (ExecutableElement)m;
 127.917 -            OnReceive onR = e.getAnnotation(OnReceive.class);
 127.918 -            if (onR == null) {
 127.919 -                continue;
 127.920 -            }
 127.921 -            if (!e.getModifiers().contains(Modifier.STATIC)) {
 127.922 -                error("@OnReceive method needs to be static", e);
 127.923 -                return false;
 127.924 -            }
 127.925 -            if (e.getModifiers().contains(Modifier.PRIVATE)) {
 127.926 -                error("@OnReceive method cannot be private", e);
 127.927 -                return false;
 127.928 -            }
 127.929 -            if (e.getReturnType().getKind() != TypeKind.VOID) {
 127.930 -                error("@OnReceive method should return void", e);
 127.931 -                return false;
 127.932 -            }
 127.933 -            if (!onR.jsonp().isEmpty() && !"GET".equals(onR.method())) {
 127.934 -                error("JSONP works only with GET transport method", e);
 127.935 -            }
 127.936 -            String dataMirror = findDataSpecified(e, onR);
 127.937 -            if ("PUT".equals(onR.method()) && dataMirror == null) {
 127.938 -                error("PUT method needs to specify a data() class", e);
 127.939 -                return false;
 127.940 -            }
 127.941 -            if ("POST".equals(onR.method()) && dataMirror == null) {
 127.942 -                error("POST method needs to specify a data() class", e);
 127.943 -                return false;
 127.944 -            }
 127.945 -            String modelClass = null;
 127.946 -            boolean expectsList = false;
 127.947 -            List<String> args = new ArrayList<String>();
 127.948 -            {
 127.949 -                for (VariableElement ve : e.getParameters()) {
 127.950 -                    TypeMirror modelType = null;
 127.951 -                    final TypeMirror type = ve.asType();
 127.952 -                    CharSequence simpleName;
 127.953 -                    if (type.getKind() == TypeKind.DECLARED) {
 127.954 -                        simpleName = ((DeclaredType)type).asElement().getSimpleName();
 127.955 -                    } else {
 127.956 -                        simpleName = type.toString();
 127.957 -                    }
 127.958 -                    if (simpleName.toString().equals(className)) {
 127.959 -                        args.add(className + ".this");
 127.960 -                    } else if (isModel(ve.asType())) {
 127.961 -                        modelType = ve.asType();
 127.962 -                    } else if (ve.asType().getKind() == TypeKind.ARRAY) {
 127.963 -                        modelType = ((ArrayType)ve.asType()).getComponentType();
 127.964 -                        expectsList = true;
 127.965 -                    } else if (ve.asType().toString().equals("java.lang.String")) {
 127.966 -                        modelType = ve.asType();
 127.967 -                    }
 127.968 -                    if (modelType != null) {
 127.969 -                        if (modelClass != null) {
 127.970 -                            error("There can be only one model class among arguments", e);
 127.971 -                        } else {
 127.972 -                            modelClass = modelType.toString();
 127.973 -                            if (expectsList) {
 127.974 -                                args.add("arr");
 127.975 -                            } else {
 127.976 -                                args.add("arr[0]");
 127.977 -                            }
 127.978 -                        }
 127.979 -                    }
 127.980 -                }
 127.981 -            }
 127.982 -            if (modelClass == null) {
 127.983 -                error("The method needs to have one @Model class as parameter", e);
 127.984 -            }
 127.985 -            String n = e.getSimpleName().toString();
 127.986 -            if ("WebSocket".equals(onR.method())) {
 127.987 -                body.append("  /** Performs WebSocket communication. Call with <code>null</code> data parameter\n");
 127.988 -                body.append("  * to open the connection (even if not required). Call with non-null data to\n");
 127.989 -                body.append("  * send messages to server. Call again with <code>null</code> data to close the socket.\n");
 127.990 -                body.append("  */\n");
 127.991 -            }
 127.992 -            body.append("  public void ").append(n).append("(");
 127.993 -            StringBuilder urlBefore = new StringBuilder();
 127.994 -            StringBuilder urlAfter = new StringBuilder();
 127.995 -            String jsonpVarName = null;
 127.996 -            {
 127.997 -                String sep = "";
 127.998 -                boolean skipJSONP = onR.jsonp().isEmpty();
 127.999 -                for (String p : findParamNames(e, onR.url(), onR.jsonp(), urlBefore, urlAfter)) {
127.1000 -                    if (!skipJSONP && p.equals(onR.jsonp())) {
127.1001 -                        skipJSONP = true;
127.1002 -                        jsonpVarName = p;
127.1003 -                        continue;
127.1004 -                    }
127.1005 -                    body.append(sep);
127.1006 -                    body.append("String ").append(p);
127.1007 -                    sep = ", ";
127.1008 -                }
127.1009 -                if (!skipJSONP) {
127.1010 -                    error(
127.1011 -                        "Name of jsonp attribute ('" + onR.jsonp() + 
127.1012 -                        "') is not used in url attribute '" + onR.url() + "'", e
127.1013 -                    );
127.1014 -                }
127.1015 -                if (dataMirror != null) {
127.1016 -                    body.append(sep).append(dataMirror.toString()).append(" data");
127.1017 -                }
127.1018 -            }
127.1019 -            body.append(") {\n");
127.1020 -            boolean webSocket = onR.method().equals("WebSocket");
127.1021 -            if (webSocket) {
127.1022 -                if (generateWSReceiveBody(body, onR, e, clazz, className, expectsList, modelClass, n, args, urlBefore, jsonpVarName, urlAfter, dataMirror)) {
127.1023 -                    return false;
127.1024 -                }
127.1025 -                body.append("  }\n");
127.1026 -                body.append("  private org.apidesign.html.json.impl.JSON.WS ws_" + e.getSimpleName() + ";\n");
127.1027 -            } else {
127.1028 -                if (generateJSONReceiveBody(body, onR, e, clazz, className, expectsList, modelClass, n, args, urlBefore, jsonpVarName, urlAfter, dataMirror)) {
127.1029 -                    return false;
127.1030 -                }
127.1031 -                body.append("  }\n");
127.1032 -            }
127.1033 -        }
127.1034 -        return true;
127.1035 -    }
127.1036 -
127.1037 -    private boolean generateJSONReceiveBody(StringWriter body, OnReceive onR, ExecutableElement e, Element clazz, String className, boolean expectsList, String modelClass, String n, List<String> args, StringBuilder urlBefore, String jsonpVarName, StringBuilder urlAfter, String dataMirror) {
127.1038 -        body.append(
127.1039 -            "    class ProcessResult extends org.apidesign.html.json.impl.RcvrJSON {\n" +
127.1040 -            "      @Override\n" +
127.1041 -            "      public void onError(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n" +
127.1042 -            "        Exception value = ev.getException();\n"
127.1043 -            );
127.1044 -        if (onR.onError().isEmpty()) {
127.1045 -            body.append(
127.1046 -                "        value.printStackTrace();\n"
127.1047 -                );
127.1048 -        } else {
127.1049 -            if (!findOnError(e, ((TypeElement)clazz), onR.onError(), className)) {
127.1050 -                return true;
127.1051 -            }
127.1052 -            body.append("        ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
127.1053 -            body.append(className).append(".this, value);\n");
127.1054 -        }
127.1055 -        body.append(
127.1056 -            "      }\n" +
127.1057 -            "      @Override\n" +
127.1058 -            "      public void onMessage(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
127.1059 -            );
127.1060 -        if (expectsList) {
127.1061 -            body.append(
127.1062 -                "        " + modelClass + "[] arr = new " + modelClass + "[ev.dataSize()];\n"
127.1063 -                );
127.1064 -        } else {
127.1065 -            body.append(
127.1066 -                "        " + modelClass + "[] arr = { null };\n"
127.1067 -                );
127.1068 -        }
127.1069 -        body.append(
127.1070 -            "        ev.dataRead(context, " + modelClass + ".class, arr);\n"
127.1071 -            );
127.1072 -        {
127.1073 -            body.append("        ").append(clazz.getSimpleName()).append(".").append(n).append("(");
127.1074 -            String sep = "";
127.1075 -            for (String arg : args) {
127.1076 -                body.append(sep);
127.1077 -                body.append(arg);
127.1078 -                sep = ", ";
127.1079 -            }
127.1080 -            body.append(");\n");
127.1081 -        }
127.1082 -        body.append(
127.1083 -            "      }\n" +
127.1084 -            "    }\n"
127.1085 -            );
127.1086 -        body.append("    ProcessResult pr = new ProcessResult();\n");
127.1087 -        body.append("    org.apidesign.html.json.impl.JSON.loadJSON(context, pr,\n        ");
127.1088 -        body.append(urlBefore).append(", ");
127.1089 -        if (jsonpVarName != null) {
127.1090 -            body.append(urlAfter);
127.1091 -        } else {
127.1092 -            body.append("null");
127.1093 -        }
127.1094 -        if (!"GET".equals(onR.method()) || dataMirror != null) {
127.1095 -            body.append(", \"").append(onR.method()).append('"');
127.1096 -            if (dataMirror != null) {
127.1097 -                body.append(", data");
127.1098 -            } else {
127.1099 -                body.append(", null");
127.1100 -            }
127.1101 -        } else {
127.1102 -            body.append(", null, null");
127.1103 -        }
127.1104 -        body.append(");\n");
127.1105 -        return false;
127.1106 -    }
127.1107 -    
127.1108 -    private boolean generateWSReceiveBody(StringWriter body, OnReceive onR, ExecutableElement e, Element clazz, String className, boolean expectsList, String modelClass, String n, List<String> args, StringBuilder urlBefore, String jsonpVarName, StringBuilder urlAfter, String dataMirror) {
127.1109 -        body.append(
127.1110 -            "    class ProcessResult extends org.apidesign.html.json.impl.RcvrJSON {\n" +
127.1111 -            "      @Override\n" +
127.1112 -            "      public void onOpen(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
127.1113 -        );
127.1114 -        body.append("        ").append(clazz.getSimpleName()).append(".").append(n).append("(");
127.1115 -        {
127.1116 -            String sep = "";
127.1117 -            for (String arg : args) {
127.1118 -                body.append(sep);
127.1119 -                if (arg.startsWith("arr")) {
127.1120 -                    body.append("null");
127.1121 -                } else {
127.1122 -                    body.append(arg);
127.1123 -                }
127.1124 -                sep = ", ";
127.1125 -            }
127.1126 -        }
127.1127 -        body.append(");\n");
127.1128 -        body.append(
127.1129 -            "      }\n" +
127.1130 -            "      @Override\n" +
127.1131 -            "      public void onError(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n" +
127.1132 -            "        Exception value = ev.getException();\n"
127.1133 -            );
127.1134 -        if (onR.onError().isEmpty()) {
127.1135 -            body.append(
127.1136 -                "        value.printStackTrace();\n"
127.1137 -                );
127.1138 -        } else {
127.1139 -            if (!findOnError(e, ((TypeElement)clazz), onR.onError(), className)) {
127.1140 -                return true;
127.1141 -            }
127.1142 -            body.append("        ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
127.1143 -            body.append(className).append(".this, value);\n");
127.1144 -        }
127.1145 -        body.append(
127.1146 -            "      }\n" +
127.1147 -            "      @Override\n" +
127.1148 -            "      public void onMessage(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
127.1149 -        );
127.1150 -        if (expectsList) {
127.1151 -            body.append(
127.1152 -                "        " + modelClass + "[] arr = new " + modelClass + "[ev.dataSize()];\n"
127.1153 -                );
127.1154 -        } else {
127.1155 -            body.append(
127.1156 -                "        " + modelClass + "[] arr = { null };\n"
127.1157 -                );
127.1158 -        }
127.1159 -        body.append(
127.1160 -            "        ev.dataRead(context, " + modelClass + ".class, arr);\n"
127.1161 -            );
127.1162 -        {
127.1163 -            body.append("        ").append(clazz.getSimpleName()).append(".").append(n).append("(");
127.1164 -            String sep = "";
127.1165 -            for (String arg : args) {
127.1166 -                body.append(sep);
127.1167 -                body.append(arg);
127.1168 -                sep = ", ";
127.1169 -            }
127.1170 -            body.append(");\n");
127.1171 -        }
127.1172 -        body.append(
127.1173 -            "      }\n"
127.1174 -        );
127.1175 -        if (!onR.onError().isEmpty()) {
127.1176 -            body.append(
127.1177 -                "      @Override\n"
127.1178 -              + "      public void onClose(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
127.1179 -            );
127.1180 -            body.append("        ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
127.1181 -            body.append(className).append(".this, null);\n");
127.1182 -            body.append(
127.1183 -                "      }\n"
127.1184 -            );
127.1185 -        }
127.1186 -        body.append("    }\n");
127.1187 -        body.append("    if (this.ws_").append(e.getSimpleName()).append(" == null) {\n");
127.1188 -        body.append("      ProcessResult pr = new ProcessResult();\n");
127.1189 -        body.append("      this.ws_").append(e.getSimpleName());
127.1190 -        body.append("= org.apidesign.html.json.impl.JSON.openWS(context, pr,\n        ");
127.1191 -        body.append(urlBefore).append(", data);\n");
127.1192 -        body.append("    } else {\n");
127.1193 -        body.append("      this.ws_").append(e.getSimpleName()).append(".send(context, ").append(urlBefore).append(", data);\n");
127.1194 -        body.append("    }\n");
127.1195 -        return false;
127.1196 -    }
127.1197 -
127.1198 -    private CharSequence wrapParams(
127.1199 -        ExecutableElement ee, String id, String className, String evName, String dataName
127.1200 -    ) {
127.1201 -        TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
127.1202 -        StringBuilder params = new StringBuilder();
127.1203 -        boolean first = true;
127.1204 -        for (VariableElement ve : ee.getParameters()) {
127.1205 -            if (!first) {
127.1206 -                params.append(", ");
127.1207 -            }
127.1208 -            first = false;
127.1209 -            String toCall = null;
127.1210 -            String toFinish = null;
127.1211 -            if (ve.asType() == stringType) {
127.1212 -                if (ve.getSimpleName().contentEquals("id")) {
127.1213 -                    params.append('"').append(id).append('"');
127.1214 -                    continue;
127.1215 -                }
127.1216 -                toCall = "org.apidesign.html.json.impl.JSON.toString(context, ";
127.1217 -            }
127.1218 -            if (ve.asType().getKind() == TypeKind.DOUBLE) {
127.1219 -                toCall = "org.apidesign.html.json.impl.JSON.toNumber(context, ";
127.1220 -                toFinish = ".doubleValue()";
127.1221 -            }
127.1222 -            if (ve.asType().getKind() == TypeKind.INT) {
127.1223 -                toCall = "org.apidesign.html.json.impl.JSON.toNumber(context, ";
127.1224 -                toFinish = ".intValue()";
127.1225 -            }
127.1226 -            if (dataName != null && ve.getSimpleName().contentEquals(dataName) && isModel(ve.asType())) {
127.1227 -                toCall = "org.apidesign.html.json.impl.JSON.toModel(context, " + ve.asType() + ".class, ";
127.1228 -            }
127.1229 -
127.1230 -            if (toCall != null) {
127.1231 -                params.append(toCall);
127.1232 -                if (dataName != null && ve.getSimpleName().contentEquals(dataName)) {
127.1233 -                    params.append(dataName);
127.1234 -                    params.append(", null");
127.1235 -                } else {
127.1236 -                    if (evName == null) {
127.1237 -                        final StringBuilder sb = new StringBuilder();
127.1238 -                        sb.append("Unexpected string parameter name.");
127.1239 -                        if (dataName != null) {
127.1240 -                            sb.append(" Try \"").append(dataName).append("\"");
127.1241 -                        }
127.1242 -                        error(sb.toString(), ee);
127.1243 -                    }
127.1244 -                    params.append(evName);
127.1245 -                    params.append(", \"");
127.1246 -                    params.append(ve.getSimpleName().toString());
127.1247 -                    params.append("\"");
127.1248 -                }
127.1249 -                params.append(")");
127.1250 -                if (toFinish != null) {
127.1251 -                    params.append(toFinish);
127.1252 -                }
127.1253 -                continue;
127.1254 -            }
127.1255 -            String rn = fqn(ve.asType(), ee);
127.1256 -            int last = rn.lastIndexOf('.');
127.1257 -            if (last >= 0) {
127.1258 -                rn = rn.substring(last + 1);
127.1259 -            }
127.1260 -            if (rn.equals(className)) {
127.1261 -                params.append(className).append(".this");
127.1262 -                continue;
127.1263 -            }
127.1264 -            error(
127.1265 -                "The annotated method can only accept " + className + " argument or argument named 'data'",
127.1266 -                ee
127.1267 -            );
127.1268 -        }
127.1269 -        return params;
127.1270 -    }
127.1271 -    
127.1272 -    
127.1273 -    private CharSequence wrapPropName(
127.1274 -        ExecutableElement ee, String className, String propName, String propValue
127.1275 -    ) {
127.1276 -        TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
127.1277 -        StringBuilder params = new StringBuilder();
127.1278 -        boolean first = true;
127.1279 -        for (VariableElement ve : ee.getParameters()) {
127.1280 -            if (!first) {
127.1281 -                params.append(", ");
127.1282 -            }
127.1283 -            first = false;
127.1284 -            if (ve.asType() == stringType) {
127.1285 -                if (propName != null && ve.getSimpleName().contentEquals(propName)) {
127.1286 -                    params.append('"').append(propValue).append('"');
127.1287 -                } else {
127.1288 -                    error("Unexpected string parameter name. Try \"" + propName + "\".", ee);
127.1289 -                }
127.1290 -                continue;
127.1291 -            }
127.1292 -            String rn = fqn(ve.asType(), ee);
127.1293 -            int last = rn.lastIndexOf('.');
127.1294 -            if (last >= 0) {
127.1295 -                rn = rn.substring(last + 1);
127.1296 -            }
127.1297 -            if (rn.equals(className)) {
127.1298 -                params.append(className).append(".this");
127.1299 -                continue;
127.1300 -            }
127.1301 -            error(
127.1302 -                "@OnPrprtChange method can only accept String or " + className + " arguments",
127.1303 -                ee);
127.1304 -        }
127.1305 -        return params;
127.1306 -    }
127.1307 -    
127.1308 -    private boolean isModel(TypeMirror tm) {
127.1309 -        if (tm.getKind() == TypeKind.ERROR) {
127.1310 -            return true;
127.1311 -        }
127.1312 -        final Element e = processingEnv.getTypeUtils().asElement(tm);
127.1313 -        if (e == null) {
127.1314 -            return false;
127.1315 -        }
127.1316 -        for (Element ch : e.getEnclosedElements()) {
127.1317 -            if (ch.getKind() == ElementKind.METHOD) {
127.1318 -                ExecutableElement ee = (ExecutableElement)ch;
127.1319 -                if (ee.getParameters().isEmpty() && ee.getSimpleName().contentEquals("modelFor")) {
127.1320 -                    return true;
127.1321 -                }
127.1322 -            }
127.1323 -        }
127.1324 -        return models.values().contains(e.getSimpleName().toString());
127.1325 -    }
127.1326 -    
127.1327 -    private void writeToString(Prprt[] props, Writer w) throws IOException {
127.1328 -        w.write("  public String toString() {\n");
127.1329 -        w.write("    StringBuilder sb = new StringBuilder();\n");
127.1330 -        w.write("    sb.append('{');\n");
127.1331 -        String sep = "";
127.1332 -        for (Prprt p : props) {
127.1333 -            w.write(sep);
127.1334 -            w.append("    sb.append('\"').append(\"" + p.name() + "\")");
127.1335 -                w.append(".append('\"').append(\":\");\n");
127.1336 -            w.append("    sb.append(org.apidesign.html.json.impl.JSON.toJSON(prop_");
127.1337 -            w.append(p.name()).append("));\n");
127.1338 -            sep =    "    sb.append(',');\n";
127.1339 -        }
127.1340 -        w.write("    sb.append('}');\n");
127.1341 -        w.write("    return sb.toString();\n");
127.1342 -        w.write("  }\n");
127.1343 -    }
127.1344 -    private void writeClone(String className, Prprt[] props, Writer w) throws IOException {
127.1345 -        w.write("  public " + className + " clone() {\n");
127.1346 -        w.write("    return clone(context);\n");
127.1347 -        w.write("  }\n");
127.1348 -        w.write("  private " + className + " clone(net.java.html.BrwsrCtx ctx) {\n");
127.1349 -        w.write("    " + className + " ret = new " + className + "(ctx);\n");
127.1350 -        for (Prprt p : props) {
127.1351 -            if (!p.array()) {
127.1352 -                boolean isModel[] = { false };
127.1353 -                boolean isEnum[] = { false };
127.1354 -                boolean isPrimitive[] = { false };
127.1355 -                checkType(p, isModel, isEnum, isPrimitive);
127.1356 -                if (!isModel[0]) {
127.1357 -                    w.write("    ret.prop_" + p.name() + " = prop_" + p.name() + ";\n");
127.1358 -                    continue;
127.1359 -                }
127.1360 -                w.write("    ret.prop_" + p.name() + " =  prop_" + p.name() + "  == null ? null : prop_" + p.name() + ".clone();\n");
127.1361 -            } else {
127.1362 -                w.write("    ret.prop_" + p.name() + ".cloneAll(ctx, prop_" + p.name() + ");\n");
127.1363 -            }
127.1364 -        }
127.1365 -        
127.1366 -        w.write("    return ret;\n");
127.1367 -        w.write("  }\n");
127.1368 -    }
127.1369 -
127.1370 -    private String inPckName(Element e) {
127.1371 -        StringBuilder sb = new StringBuilder();
127.1372 -        while (e.getKind() != ElementKind.PACKAGE) {
127.1373 -            if (sb.length() == 0) {
127.1374 -                sb.append(e.getSimpleName());
127.1375 -            } else {
127.1376 -                sb.insert(0, '.');
127.1377 -                sb.insert(0, e.getSimpleName());
127.1378 -            }
127.1379 -            e = e.getEnclosingElement();
127.1380 -        }
127.1381 -        return sb.toString();
127.1382 -    }
127.1383 -
127.1384 -    private String fqn(TypeMirror pt, Element relative) {
127.1385 -        if (pt.getKind() == TypeKind.ERROR) {
127.1386 -            final Elements eu = processingEnv.getElementUtils();
127.1387 -            PackageElement pckg = eu.getPackageOf(relative);
127.1388 -            return pckg.getQualifiedName() + "." + pt.toString();
127.1389 -        }
127.1390 -        return pt.toString();
127.1391 -    }
127.1392 -
127.1393 -    private String checkType(Prprt p, boolean[] isModel, boolean[] isEnum, boolean[] isPrimitive) {
127.1394 -        TypeMirror tm;
127.1395 -        try {
127.1396 -            String ret = p.typeName(processingEnv);
127.1397 -            TypeElement e = processingEnv.getElementUtils().getTypeElement(ret);
127.1398 -            if (e == null) {
127.1399 -                isModel[0] = true;
127.1400 -                isEnum[0] = false;
127.1401 -                isPrimitive[0] = false;
127.1402 -                return ret;
127.1403 -            }
127.1404 -            tm = e.asType();
127.1405 -        } catch (MirroredTypeException ex) {
127.1406 -            tm = ex.getTypeMirror();
127.1407 -        }
127.1408 -        tm = processingEnv.getTypeUtils().erasure(tm);
127.1409 -        if (isPrimitive[0] = tm.getKind().isPrimitive()) {
127.1410 -            isEnum[0] = false;
127.1411 -            isModel[0] = false;
127.1412 -            return tm.toString();
127.1413 -        }
127.1414 -        final Element e = processingEnv.getTypeUtils().asElement(tm);
127.1415 -        if (e.getKind() == ElementKind.CLASS && tm.getKind() == TypeKind.ERROR) {
127.1416 -            isModel[0] = true;
127.1417 -            isEnum[0] = false;
127.1418 -            return e.getSimpleName().toString();
127.1419 -        }
127.1420 -        
127.1421 -        final Model m = e == null ? null : e.getAnnotation(Model.class);
127.1422 -        String ret;
127.1423 -        if (m != null) {
127.1424 -            ret = findPkgName(e) + '.' + m.className();
127.1425 -            isModel[0] = true;
127.1426 -            models.put(e, m.className());
127.1427 -        } else if (findModelForMthd(e)) {
127.1428 -            ret = ((TypeElement)e).getQualifiedName().toString();
127.1429 -            isModel[0] = true;
127.1430 -        } else {
127.1431 -            ret = tm.toString();
127.1432 -        }
127.1433 -        TypeMirror enm = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType();
127.1434 -        enm = processingEnv.getTypeUtils().erasure(enm);
127.1435 -        isEnum[0] = processingEnv.getTypeUtils().isSubtype(tm, enm);
127.1436 -        return ret;
127.1437 -    }
127.1438 -    
127.1439 -    private static boolean findModelForMthd(Element clazz) {
127.1440 -        if (clazz == null) {
127.1441 -            return false;
127.1442 -        }
127.1443 -        for (Element e : clazz.getEnclosedElements()) {
127.1444 -            if (e.getKind() == ElementKind.METHOD) {
127.1445 -                ExecutableElement ee = (ExecutableElement)e;
127.1446 -                if (
127.1447 -                    ee.getSimpleName().contentEquals("modelFor") &&
127.1448 -                    ee.getParameters().isEmpty()
127.1449 -                ) {
127.1450 -                    return true;
127.1451 -                }
127.1452 -            }
127.1453 -        }
127.1454 -        return false;
127.1455 -    }
127.1456 -
127.1457 -    private Iterable<String> findParamNames(
127.1458 -        Element e, String url, String jsonParam, StringBuilder... both
127.1459 -    ) {
127.1460 -        List<String> params = new ArrayList<String>();
127.1461 -        int wasJSON = 0;
127.1462 -
127.1463 -        for (int pos = 0; ;) {
127.1464 -            int next = url.indexOf('{', pos);
127.1465 -            if (next == -1) {
127.1466 -                both[wasJSON].append('"')
127.1467 -                    .append(url.substring(pos))
127.1468 -                    .append('"');
127.1469 -                return params;
127.1470 -            }
127.1471 -            int close = url.indexOf('}', next);
127.1472 -            if (close == -1) {
127.1473 -                error("Unbalanced '{' and '}' in " + url, e);
127.1474 -                return params;
127.1475 -            }
127.1476 -            final String paramName = url.substring(next + 1, close);
127.1477 -            params.add(paramName);
127.1478 -            if (paramName.equals(jsonParam) && !jsonParam.isEmpty()) {
127.1479 -                both[wasJSON].append('"')
127.1480 -                    .append(url.substring(pos, next))
127.1481 -                    .append('"');
127.1482 -                wasJSON = 1;
127.1483 -            } else {
127.1484 -                both[wasJSON].append('"')
127.1485 -                    .append(url.substring(pos, next))
127.1486 -                    .append("\" + ").append(paramName).append(" + ");
127.1487 -            }
127.1488 -            pos = close + 1;
127.1489 -        }
127.1490 -    }
127.1491 -
127.1492 -    private static Prprt findPrprt(Prprt[] properties, String propName) {
127.1493 -        for (Prprt p : properties) {
127.1494 -            if (propName.equals(p.name())) {
127.1495 -                return p;
127.1496 -            }
127.1497 -        }
127.1498 -        return null;
127.1499 -    }
127.1500 -
127.1501 -    private boolean isPrimitive(String type) {
127.1502 -        return 
127.1503 -            "int".equals(type) ||
127.1504 -            "double".equals(type) ||
127.1505 -            "long".equals(type) ||
127.1506 -            "short".equals(type) ||
127.1507 -            "byte".equals(type) ||
127.1508 -            "char".equals(type) ||
127.1509 -            "boolean".equals(type) ||
127.1510 -            "float".equals(type);
127.1511 -    }
127.1512 -
127.1513 -    private static Collection<String> findDerivedFrom(Map<String, Collection<String>> propsDeps, String derivedProp) {
127.1514 -        Set<String> names = new HashSet<String>();
127.1515 -        for (Map.Entry<String, Collection<String>> e : propsDeps.entrySet()) {
127.1516 -            if (e.getValue().contains(derivedProp)) {
127.1517 -                names.add(e.getKey());
127.1518 -            }
127.1519 -        }
127.1520 -        return names;
127.1521 -    }
127.1522 -    
127.1523 -    private Prprt[] createProps(Element e, Property[] arr) {
127.1524 -        Prprt[] ret = Prprt.wrap(processingEnv, e, arr);
127.1525 -        Prprt[] prev = verify.put(e, ret);
127.1526 -        if (prev != null) {
127.1527 -            error("Two sets of properties for ", e);
127.1528 -        }
127.1529 -        return ret;
127.1530 -    }
127.1531 -    
127.1532 -    private static String strip(String s) {
127.1533 -        int indx = s.indexOf("__");
127.1534 -        if (indx >= 0) {
127.1535 -            return s.substring(0, indx);
127.1536 -        } else {
127.1537 -            return s;
127.1538 -        }
127.1539 -    }
127.1540 -
127.1541 -    private String findDataSpecified(ExecutableElement e, OnReceive onR) {
127.1542 -        try {
127.1543 -            return onR.data().getName();
127.1544 -        } catch (MirroredTypeException ex) {
127.1545 -            final TypeMirror tm = ex.getTypeMirror();
127.1546 -            String name;
127.1547 -            final Element te = processingEnv.getTypeUtils().asElement(tm);
127.1548 -            if (te.getKind() == ElementKind.CLASS && tm.getKind() == TypeKind.ERROR) {
127.1549 -                name = te.getSimpleName().toString();
127.1550 -            } else {
127.1551 -                name = tm.toString();
127.1552 -            }
127.1553 -            return "java.lang.Object".equals(name) ? null : name;
127.1554 -        } catch (Exception ex) {
127.1555 -            // fallback
127.1556 -        }
127.1557 -        
127.1558 -        AnnotationMirror found = null;
127.1559 -        for (AnnotationMirror am : e.getAnnotationMirrors()) {
127.1560 -            if (am.getAnnotationType().toString().equals(OnReceive.class.getName())) {
127.1561 -                found = am;
127.1562 -            }
127.1563 -        }
127.1564 -        if (found == null) {
127.1565 -            return null;
127.1566 -        }
127.1567 -        
127.1568 -        for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : found.getElementValues().entrySet()) {
127.1569 -            ExecutableElement ee = entry.getKey();
127.1570 -            AnnotationValue av = entry.getValue();
127.1571 -            if (ee.getSimpleName().contentEquals("data")) {
127.1572 -                List<? extends Object> values = getAnnoValues(processingEnv, e, found);
127.1573 -                for (Object v : values) {
127.1574 -                    String sv = v.toString();
127.1575 -                    if (sv.startsWith("data = ") && sv.endsWith(".class")) {
127.1576 -                        return sv.substring(7, sv.length() - 6);
127.1577 -                    }
127.1578 -                }
127.1579 -                return "error";
127.1580 -            }
127.1581 -        }
127.1582 -        return null;
127.1583 -    }
127.1584 -
127.1585 -    static List<? extends Object> getAnnoValues(ProcessingEnvironment pe, Element e, AnnotationMirror am) {
127.1586 -        try {
127.1587 -            Class<?> trees = Class.forName("com.sun.tools.javac.api.JavacTrees");
127.1588 -            Method m = trees.getMethod("instance", ProcessingEnvironment.class);
127.1589 -            Object instance = m.invoke(null, pe);
127.1590 -            m = instance.getClass().getMethod("getPath", Element.class, AnnotationMirror.class);
127.1591 -            Object path = m.invoke(instance, e, am);
127.1592 -            m = path.getClass().getMethod("getLeaf");
127.1593 -            Object leaf = m.invoke(path);
127.1594 -            m = leaf.getClass().getMethod("getArguments");
127.1595 -            return (List) m.invoke(leaf);
127.1596 -        } catch (Exception ex) {
127.1597 -            return Collections.emptyList();
127.1598 -        }
127.1599 -    }
127.1600 -
127.1601 -    private static class Prprt {
127.1602 -        private final Element e;
127.1603 -        private final AnnotationMirror tm;
127.1604 -        private final Property p;
127.1605 -
127.1606 -        public Prprt(Element e, AnnotationMirror tm, Property p) {
127.1607 -            this.e = e;
127.1608 -            this.tm = tm;
127.1609 -            this.p = p;
127.1610 -        }
127.1611 -        
127.1612 -        String name() {
127.1613 -            return p.name();
127.1614 -        }
127.1615 -        
127.1616 -        boolean array() {
127.1617 -            return p.array();
127.1618 -        }
127.1619 -
127.1620 -        String typeName(ProcessingEnvironment env) {
127.1621 -            RuntimeException ex;
127.1622 -            try {
127.1623 -                return p.type().getName();
127.1624 -            } catch (IncompleteAnnotationException e) {
127.1625 -                ex = e;
127.1626 -            } catch (AnnotationTypeMismatchException e) {
127.1627 -                ex = e;
127.1628 -            }
127.1629 -            for (Object v : getAnnoValues(env, e, tm)) {
127.1630 -                String s = v.toString().replace(" ", "");
127.1631 -                if (s.startsWith("type=") && s.endsWith(".class")) {
127.1632 -                    return s.substring(5, s.length() - 6);
127.1633 -                }
127.1634 -            }
127.1635 -            throw ex;
127.1636 -        }
127.1637 -        
127.1638 -        
127.1639 -        static Prprt[] wrap(ProcessingEnvironment pe, Element e, Property[] arr) {
127.1640 -            if (arr.length == 0) {
127.1641 -                return new Prprt[0];
127.1642 -            }
127.1643 -            
127.1644 -            if (e.getKind() != ElementKind.CLASS) {
127.1645 -                throw new IllegalStateException("" + e.getKind());
127.1646 -            }
127.1647 -            TypeElement te = (TypeElement)e;
127.1648 -            List<? extends AnnotationValue> val = null;
127.1649 -            for (AnnotationMirror an : te.getAnnotationMirrors()) {
127.1650 -                for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : an.getElementValues().entrySet()) {
127.1651 -                    if (entry.getKey().getSimpleName().contentEquals("properties")) {
127.1652 -                        val = (List)entry.getValue().getValue();
127.1653 -                        break;
127.1654 -                    }
127.1655 -                }
127.1656 -            }
127.1657 -            if (val == null || val.size() != arr.length) {
127.1658 -                pe.getMessager().printMessage(Diagnostic.Kind.ERROR, "" + val, e);
127.1659 -                return new Prprt[0];
127.1660 -            }
127.1661 -            Prprt[] ret = new Prprt[arr.length];
127.1662 -            BIG: for (int i = 0; i < ret.length; i++) {
127.1663 -                AnnotationMirror am = (AnnotationMirror)val.get(i).getValue();
127.1664 -                ret[i] = new Prprt(e, am, arr[i]);
127.1665 -                
127.1666 -            }
127.1667 -            return ret;
127.1668 -        }
127.1669 -    }
127.1670 -
127.1671 -    @Override
127.1672 -    public Iterable<? extends Completion> getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) {
127.1673 -        final Level l = Level.FINE;
127.1674 -        LOG.log(l, " element: {0}", element);
127.1675 -        LOG.log(l, " annotation: {0}", annotation);
127.1676 -        LOG.log(l, " member: {0}", member);
127.1677 -        LOG.log(l, " userText: {0}", userText);
127.1678 -        LOG.log(l, "str: {0}", annotation.getAnnotationType().toString());
127.1679 -        if (annotation.getAnnotationType().toString().equals(OnReceive.class.getName())) {
127.1680 -            if (member.getSimpleName().contentEquals("method")) {
127.1681 -                return Arrays.asList(
127.1682 -                    methodOf("GET"),
127.1683 -                    methodOf("POST"),
127.1684 -                    methodOf("PUT"),
127.1685 -                    methodOf("DELETE"),
127.1686 -                    methodOf("HEAD"),
127.1687 -                    methodOf("WebSocket")
127.1688 -                );
127.1689 -            }
127.1690 -        }
127.1691 -        
127.1692 -        return super.getCompletions(element, annotation, member, userText);
127.1693 -    }
127.1694 -    
127.1695 -    private static final Completion methodOf(String method) {
127.1696 -        ResourceBundle rb = ResourceBundle.getBundle("org.apidesign.html.json.impl.Bundle");
127.1697 -        return Completions.of('"' + method + '"', rb.getString("MSG_Completion_" + method));
127.1698 -    }
127.1699 -    
127.1700 -    private boolean findOnError(ExecutableElement errElem, TypeElement te, String name, String className) {
127.1701 -        String err = null;
127.1702 -        METHODS:
127.1703 -        for (Element e : te.getEnclosedElements()) {
127.1704 -            if (e.getKind() != ElementKind.METHOD) {
127.1705 -                continue;
127.1706 -            }
127.1707 -            if (!e.getSimpleName().contentEquals(name)) {
127.1708 -                continue;
127.1709 -            }
127.1710 -            if (!e.getModifiers().contains(Modifier.STATIC)) {
127.1711 -                errElem = (ExecutableElement) e;
127.1712 -                err = "Would have to be static";
127.1713 -                continue;
127.1714 -            }
127.1715 -            ExecutableElement ee = (ExecutableElement) e;
127.1716 -            TypeMirror excType = processingEnv.getElementUtils().getTypeElement(Exception.class.getName()).asType();
127.1717 -            final List<? extends VariableElement> params = ee.getParameters();
127.1718 -            boolean error = false;
127.1719 -            if (params.size() != 2) {
127.1720 -                error = true;
127.1721 -            } else {
127.1722 -                String firstType = params.get(0).asType().toString();
127.1723 -                int lastDot = firstType.lastIndexOf('.');
127.1724 -                if (lastDot != -1) {
127.1725 -                    firstType = firstType.substring(lastDot + 1);
127.1726 -                }
127.1727 -                if (!firstType.equals(className)) {
127.1728 -                    error = true;
127.1729 -                }
127.1730 -                if (!processingEnv.getTypeUtils().isAssignable(excType, params.get(1).asType())) {
127.1731 -                    error = true;
127.1732 -                }
127.1733 -            }
127.1734 -            if (error) {
127.1735 -                errElem = (ExecutableElement) e;
127.1736 -                err = "Error method first argument needs to be " + className + " and second Exception";
127.1737 -                continue;
127.1738 -            }
127.1739 -            return true;
127.1740 -        }
127.1741 -        if (err == null) {
127.1742 -            err = "Cannot find " + name + "(" + className + ", Exception) method in this class";
127.1743 -        }
127.1744 -        error(err, errElem);
127.1745 -        return false;
127.1746 -    }
127.1747 -    
127.1748 -}
   128.1 --- a/json/src/main/java/org/apidesign/html/json/impl/PropertyBindingAccessor.java	Thu Dec 19 17:11:01 2013 +0100
   128.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   128.3 @@ -1,113 +0,0 @@
   128.4 -/**
   128.5 - * HTML via Java(tm) Language Bindings
   128.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   128.7 - *
   128.8 - * This program is free software: you can redistribute it and/or modify
   128.9 - * it under the terms of the GNU General Public License as published by
  128.10 - * the Free Software Foundation, version 2 of the License.
  128.11 - *
  128.12 - * This program is distributed in the hope that it will be useful,
  128.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  128.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  128.15 - * GNU General Public License for more details. apidesign.org
  128.16 - * designates this particular file as subject to the
  128.17 - * "Classpath" exception as provided by apidesign.org
  128.18 - * in the License file that accompanied this code.
  128.19 - *
  128.20 - * You should have received a copy of the GNU General Public License
  128.21 - * along with this program. Look for COPYING file in the top folder.
  128.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  128.23 - */
  128.24 -package org.apidesign.html.json.impl;
  128.25 -
  128.26 -import net.java.html.BrwsrCtx;
  128.27 -import org.apidesign.html.json.spi.FunctionBinding;
  128.28 -import org.apidesign.html.json.spi.JSONCall;
  128.29 -import org.apidesign.html.json.spi.PropertyBinding;
  128.30 -
  128.31 -/**
  128.32 - *
  128.33 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  128.34 - */
  128.35 -public abstract class PropertyBindingAccessor {
  128.36 -    private static PropertyBindingAccessor DEFAULT;
  128.37 -
  128.38 -    protected PropertyBindingAccessor() {
  128.39 -        if (DEFAULT != null) throw new IllegalStateException();
  128.40 -        DEFAULT = this;
  128.41 -    }
  128.42 -    
  128.43 -    static {
  128.44 -        JSON.initClass(PropertyBinding.class);
  128.45 -    }
  128.46 -
  128.47 -    protected abstract <M> PropertyBinding newBinding(PBData<M> d);
  128.48 -    protected abstract <M> FunctionBinding newFunction(FBData<M> d);
  128.49 -    protected abstract JSONCall newCall(
  128.50 -        BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter,
  128.51 -        String method, Object data
  128.52 -    );
  128.53 -
  128.54 -    
  128.55 -    static <M> PropertyBinding create(PBData<M> d) {
  128.56 -        return DEFAULT.newBinding(d);
  128.57 -    }
  128.58 -    static <M> FunctionBinding createFunction(FBData<M> d) {
  128.59 -        return DEFAULT.newFunction(d);
  128.60 -    }
  128.61 -    static JSONCall createCall(
  128.62 -        BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter, 
  128.63 -        String method, Object data
  128.64 -    ) {
  128.65 -        return DEFAULT.newCall(ctx, callback, urlBefore, urlAfter, method, data);
  128.66 -    }
  128.67 -
  128.68 -    public static final class PBData<M> {
  128.69 -        public final String name;
  128.70 -        public final boolean readOnly;
  128.71 -        private final M model;
  128.72 -        private final SetAndGet<M> access;
  128.73 -        private final Bindings<?> bindings;
  128.74 -
  128.75 -        public PBData(Bindings<?> bindings, String name, M model, SetAndGet<M> access, boolean readOnly) {
  128.76 -            this.bindings = bindings;
  128.77 -            this.name = name;
  128.78 -            this.model = model;
  128.79 -            this.access = access;
  128.80 -            this.readOnly = readOnly;
  128.81 -        }
  128.82 -
  128.83 -        public void setValue(Object v) {
  128.84 -            access.setValue(model, v);
  128.85 -        }
  128.86 -
  128.87 -        public Object getValue() {
  128.88 -            return access.getValue(model);
  128.89 -        }
  128.90 -
  128.91 -        public boolean isReadOnly() {
  128.92 -            return readOnly;
  128.93 -        }
  128.94 -
  128.95 -        public Bindings getBindings() {
  128.96 -            return bindings;
  128.97 -        }
  128.98 -    } // end of PBData
  128.99 -    
 128.100 -    public static final class FBData<M> {
 128.101 -        public final String name;
 128.102 -        private final M model;
 128.103 -        private final Callback<M> access;
 128.104 -
 128.105 -        public FBData(String name, M model, Callback<M> access) {
 128.106 -            this.name = name;
 128.107 -            this.model = model;
 128.108 -            this.access = access;
 128.109 -        }
 128.110 -
 128.111 -
 128.112 -        public void call(Object data, Object ev) {
 128.113 -            access.call(model, data, ev);
 128.114 -        }
 128.115 -    } // end of FBData
 128.116 -}
   129.1 --- a/json/src/main/java/org/apidesign/html/json/impl/RcvrJSON.java	Thu Dec 19 17:11:01 2013 +0100
   129.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   129.3 @@ -1,127 +0,0 @@
   129.4 -/**
   129.5 - * HTML via Java(tm) Language Bindings
   129.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   129.7 - *
   129.8 - * This program is free software: you can redistribute it and/or modify
   129.9 - * it under the terms of the GNU General Public License as published by
  129.10 - * the Free Software Foundation, version 2 of the License.
  129.11 - *
  129.12 - * This program is distributed in the hope that it will be useful,
  129.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  129.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  129.15 - * GNU General Public License for more details. apidesign.org
  129.16 - * designates this particular file as subject to the
  129.17 - * "Classpath" exception as provided by apidesign.org
  129.18 - * in the License file that accompanied this code.
  129.19 - *
  129.20 - * You should have received a copy of the GNU General Public License
  129.21 - * along with this program. Look for COPYING file in the top folder.
  129.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  129.23 - */
  129.24 -package org.apidesign.html.json.impl;
  129.25 -
  129.26 -import net.java.html.BrwsrCtx;
  129.27 -
  129.28 -/** Super type for those who wish to receive JSON messages.
  129.29 - *
  129.30 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  129.31 - */
  129.32 -public abstract class RcvrJSON {
  129.33 -    protected void onOpen(MsgEvnt msg) {}
  129.34 -    protected abstract void onMessage(MsgEvnt msg);
  129.35 -    protected void onClose(MsgEvnt msg) {}
  129.36 -    protected abstract void onError(MsgEvnt msg);
  129.37 -    
  129.38 -    public abstract static class MsgEvnt {
  129.39 -        MsgEvnt() {
  129.40 -        }
  129.41 -        
  129.42 -        public Throwable getError() {
  129.43 -            return null;
  129.44 -        }
  129.45 -        
  129.46 -        public final Exception getException() {
  129.47 -            Throwable t = getError();
  129.48 -            if (t instanceof Exception) {
  129.49 -                return (Exception)t;
  129.50 -            }
  129.51 -            if (t == null) {
  129.52 -                return null;
  129.53 -            }
  129.54 -            return new Exception(t);
  129.55 -        }
  129.56 -        
  129.57 -        public int dataSize() {
  129.58 -            return -1;
  129.59 -        }
  129.60 -        
  129.61 -        public <Data> void dataRead(BrwsrCtx ctx, Class<? extends Data> type, Data[] fillTheArray) {
  129.62 -        }
  129.63 -
  129.64 -        public abstract void dispatch(RcvrJSON r);
  129.65 -        
  129.66 -        public static MsgEvnt createError(final Throwable t) {
  129.67 -            return new MsgEvnt() {
  129.68 -                @Override
  129.69 -                public Throwable getError() {
  129.70 -                    return t;
  129.71 -                }
  129.72 -
  129.73 -                @Override
  129.74 -                public void dispatch(RcvrJSON r) {
  129.75 -                    r.onError(this);
  129.76 -                }
  129.77 -            };
  129.78 -        }
  129.79 -        
  129.80 -        public static MsgEvnt createMessage(final Object value) {
  129.81 -            return new MsgEvnt() {
  129.82 -                @Override
  129.83 -                public int dataSize() {
  129.84 -                    if (value instanceof Object[]) {
  129.85 -                        return ((Object[])value).length;
  129.86 -                    } else {
  129.87 -                        return 1;
  129.88 -                    }
  129.89 -                }
  129.90 -                
  129.91 -                @Override
  129.92 -                public <Data> void dataRead(BrwsrCtx context, Class<? extends Data> type, Data[] arr) {
  129.93 -                    if (value instanceof Object[]) {
  129.94 -                        Object[] data = ((Object[]) value);
  129.95 -                        for (int i = 0; i < data.length && i < arr.length; i++) {
  129.96 -                            arr[i] = org.apidesign.html.json.impl.JSON.read(context, type, data[i]);
  129.97 -                        }
  129.98 -                    } else {
  129.99 -                        if (arr.length > 0) {
 129.100 -                            arr[0] = org.apidesign.html.json.impl.JSON.read(context, type, value);
 129.101 -                        }
 129.102 -                    }
 129.103 -                }
 129.104 -                
 129.105 -                @Override
 129.106 -                public void dispatch(RcvrJSON r) {
 129.107 -                    r.onMessage(this);
 129.108 -                }
 129.109 -            };
 129.110 -        }
 129.111 -        
 129.112 -        public static MsgEvnt createOpen() {
 129.113 -            return new MsgEvnt() {
 129.114 -                @Override
 129.115 -                public void dispatch(RcvrJSON r) {
 129.116 -                    r.onOpen(this);
 129.117 -                }
 129.118 -            };
 129.119 -        }
 129.120 -
 129.121 -        public static MsgEvnt createClose() {
 129.122 -            return new MsgEvnt() {
 129.123 -                @Override
 129.124 -                public void dispatch(RcvrJSON r) {
 129.125 -                    r.onClose(this);
 129.126 -                }
 129.127 -            };
 129.128 -        }
 129.129 -    } // end MsgEvnt
 129.130 -}
   130.1 --- a/json/src/main/java/org/apidesign/html/json/impl/SetAndGet.java	Thu Dec 19 17:11:01 2013 +0100
   130.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   130.3 @@ -1,33 +0,0 @@
   130.4 -/**
   130.5 - * HTML via Java(tm) Language Bindings
   130.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   130.7 - *
   130.8 - * This program is free software: you can redistribute it and/or modify
   130.9 - * it under the terms of the GNU General Public License as published by
  130.10 - * the Free Software Foundation, version 2 of the License.
  130.11 - *
  130.12 - * This program is distributed in the hope that it will be useful,
  130.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  130.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  130.15 - * GNU General Public License for more details. apidesign.org
  130.16 - * designates this particular file as subject to the
  130.17 - * "Classpath" exception as provided by apidesign.org
  130.18 - * in the License file that accompanied this code.
  130.19 - *
  130.20 - * You should have received a copy of the GNU General Public License
  130.21 - * along with this program. Look for COPYING file in the top folder.
  130.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  130.23 - */
  130.24 -
  130.25 -package org.apidesign.html.json.impl;
  130.26 -
  130.27 -import org.apidesign.html.json.spi.PropertyBinding;
  130.28 -
  130.29 -/** A way to implement a {@link PropertyBinding}.
  130.30 - *
  130.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  130.32 - */
  130.33 -public interface SetAndGet<Data> {
  130.34 -    public void setValue(Data data, Object value);
  130.35 -    public Object getValue(Data data);
  130.36 -}
   131.1 --- a/json/src/main/java/org/apidesign/html/json/impl/WrapperObject.java	Thu Dec 19 17:11:01 2013 +0100
   131.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   131.3 @@ -1,61 +0,0 @@
   131.4 -/**
   131.5 - * HTML via Java(tm) Language Bindings
   131.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   131.7 - *
   131.8 - * This program is free software: you can redistribute it and/or modify
   131.9 - * it under the terms of the GNU General Public License as published by
  131.10 - * the Free Software Foundation, version 2 of the License.
  131.11 - *
  131.12 - * This program is distributed in the hope that it will be useful,
  131.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  131.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  131.15 - * GNU General Public License for more details. apidesign.org
  131.16 - * designates this particular file as subject to the
  131.17 - * "Classpath" exception as provided by apidesign.org
  131.18 - * in the License file that accompanied this code.
  131.19 - *
  131.20 - * You should have received a copy of the GNU General Public License
  131.21 - * along with this program. Look for COPYING file in the top folder.
  131.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  131.23 - */
  131.24 -
  131.25 -package org.apidesign.html.json.impl;
  131.26 -
  131.27 -import java.util.Collection;
  131.28 -import org.apidesign.html.json.impl.PropertyBindingAccessor.PBData;
  131.29 -
  131.30 -/** A way to extract real object from a model classes.
  131.31 - *
  131.32 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  131.33 - */
  131.34 -public final class WrapperObject {
  131.35 -    private Object ko;
  131.36 -    
  131.37 -    private WrapperObject() {
  131.38 -    }
  131.39 -    
  131.40 -    public void setRealObject(Object ko) {
  131.41 -        this.ko = ko;
  131.42 -    }
  131.43 -    
  131.44 -    public static Object find(Object object) {
  131.45 -        return find(object, null);
  131.46 -    }
  131.47 -    
  131.48 -    public static Object find(Object object, Bindings model) {
  131.49 -        if (object == null) {
  131.50 -            return null;
  131.51 -        }
  131.52 -        
  131.53 -        if (object instanceof JSONList) {
  131.54 -            return ((JSONList<?>)object).koData();
  131.55 -        }
  131.56 -        if (object instanceof Collection) {
  131.57 -            return JSONList.koData((Collection<?>)object, model);
  131.58 -        }
  131.59 -        
  131.60 -        WrapperObject ro = new WrapperObject();
  131.61 -        object.equals(ro);
  131.62 -        return ro.ko;
  131.63 -    }
  131.64 -}
   132.1 --- a/json/src/main/java/org/apidesign/html/json/spi/FunctionBinding.java	Thu Dec 19 17:11:01 2013 +0100
   132.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/FunctionBinding.java	Tue Jan 07 08:21:57 2014 +0100
   132.3 @@ -1,56 +1,102 @@
   132.4  /**
   132.5 - * HTML via Java(tm) Language Bindings
   132.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   132.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   132.8   *
   132.9 - * This program is free software: you can redistribute it and/or modify
  132.10 - * it under the terms of the GNU General Public License as published by
  132.11 - * the Free Software Foundation, version 2 of the License.
  132.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  132.13   *
  132.14 - * This program is distributed in the hope that it will be useful,
  132.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  132.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  132.17 - * GNU General Public License for more details. apidesign.org
  132.18 - * designates this particular file as subject to the
  132.19 - * "Classpath" exception as provided by apidesign.org
  132.20 - * in the License file that accompanied this code.
  132.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  132.22 + * Other names may be trademarks of their respective owners.
  132.23   *
  132.24 - * You should have received a copy of the GNU General Public License
  132.25 - * along with this program. Look for COPYING file in the top folder.
  132.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  132.27 + * The contents of this file are subject to the terms of either the GNU
  132.28 + * General Public License Version 2 only ("GPL") or the Common
  132.29 + * Development and Distribution License("CDDL") (collectively, the
  132.30 + * "License"). You may not use this file except in compliance with the
  132.31 + * License. You can obtain a copy of the License at
  132.32 + * http://www.netbeans.org/cddl-gplv2.html
  132.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  132.34 + * specific language governing permissions and limitations under the
  132.35 + * License.  When distributing the software, include this License Header
  132.36 + * Notice in each file and include the License file at
  132.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  132.38 + * particular file as subject to the "Classpath" exception as provided
  132.39 + * by Oracle in the GPL Version 2 section of the License file that
  132.40 + * accompanied this code. If applicable, add the following below the
  132.41 + * License Header, with the fields enclosed by brackets [] replaced by
  132.42 + * your own identifying information:
  132.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  132.44 + *
  132.45 + * Contributor(s):
  132.46 + *
  132.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  132.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  132.49 + *
  132.50 + * If you wish your version of this file to be governed by only the CDDL
  132.51 + * or only the GPL Version 2, indicate your decision by adding
  132.52 + * "[Contributor] elects to include this software in this distribution
  132.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  132.54 + * single choice of license, a recipient has the option to distribute
  132.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  132.56 + * to extend the choice of license to its licensees as provided above.
  132.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  132.58 + * Version 2 license, then the option applies only if the new code is
  132.59 + * made subject to such option by the copyright holder.
  132.60   */
  132.61  package org.apidesign.html.json.spi;
  132.62  
  132.63  import net.java.html.json.Function;
  132.64  import net.java.html.json.Model;
  132.65 -import org.apidesign.html.json.impl.PropertyBindingAccessor.FBData;
  132.66  
  132.67  /** Describes a function provided by the {@link Model} and 
  132.68   * annotated by {@link Function} annotation.
  132.69   *
  132.70   * @author Jaroslav Tulach <jtulach@netbeans.org>
  132.71   */
  132.72 -public final class FunctionBinding {
  132.73 -    private final FBData<?> fb;
  132.74 -    
  132.75 -    FunctionBinding(FBData<?> fb) {
  132.76 -        this.fb = fb;
  132.77 -    }
  132.78 -
  132.79 -    public String getFunctionName() {
  132.80 -        return fb.name;
  132.81 +public abstract class FunctionBinding {
  132.82 +    FunctionBinding() {
  132.83      }
  132.84      
  132.85 -    /** Calls the function provided data associated with current element,
  132.86 -     * as well as information about the event that triggered the event.
  132.87 -     * 
  132.88 +    /** Returns name of the function.
  132.89 +     * @return function name
  132.90 +     */
  132.91 +    public abstract String getFunctionName();
  132.92 +    
  132.93 +    /**
  132.94 +     * Calls the function provided data associated with current element, as well
  132.95 +     * as information about the event that triggered the event.
  132.96 +     *
  132.97       * @param data data associated with selected element
  132.98       * @param ev event (with additional properties) that triggered the event
  132.99       */
 132.100 -    public void call(Object data, Object ev) {
 132.101 -        try {
 132.102 -            fb.call(data, ev);
 132.103 -        } catch (Throwable ex) {
 132.104 -            ex.printStackTrace();
 132.105 +    public abstract void call(Object data, Object ev);
 132.106 +
 132.107 +    static <M> FunctionBinding registerFunction(String name, int index, M model, Proto.Type<M> access) {
 132.108 +        return new Impl<M>(name, index, model, access);
 132.109 +    }
 132.110 +    
 132.111 +    private static final class Impl<M> extends FunctionBinding {
 132.112 +        final String name;
 132.113 +        private final M model;
 132.114 +        private final Proto.Type<M> access;
 132.115 +        private final int index;
 132.116 +
 132.117 +        public Impl(String name, int index, M model, Proto.Type<M> access) {
 132.118 +            this.name = name;
 132.119 +            this.index = index;
 132.120 +            this.model = model;
 132.121 +            this.access = access;
 132.122 +        }
 132.123 +
 132.124 +        @Override
 132.125 +        public String getFunctionName() {
 132.126 +            return name;
 132.127 +        }
 132.128 +
 132.129 +        @Override
 132.130 +        public void call(Object data, Object ev) {
 132.131 +            try {
 132.132 +                access.call(model, index, data, ev);
 132.133 +            } catch (Throwable ex) {
 132.134 +                ex.printStackTrace();
 132.135 +            }
 132.136          }
 132.137      }
 132.138  }
   133.1 --- a/json/src/main/java/org/apidesign/html/json/spi/JSONCall.java	Thu Dec 19 17:11:01 2013 +0100
   133.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/JSONCall.java	Tue Jan 07 08:21:57 2014 +0100
   133.3 @@ -1,31 +1,52 @@
   133.4  /**
   133.5 - * HTML via Java(tm) Language Bindings
   133.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   133.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   133.8   *
   133.9 - * This program is free software: you can redistribute it and/or modify
  133.10 - * it under the terms of the GNU General Public License as published by
  133.11 - * the Free Software Foundation, version 2 of the License.
  133.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  133.13   *
  133.14 - * This program is distributed in the hope that it will be useful,
  133.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  133.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  133.17 - * GNU General Public License for more details. apidesign.org
  133.18 - * designates this particular file as subject to the
  133.19 - * "Classpath" exception as provided by apidesign.org
  133.20 - * in the License file that accompanied this code.
  133.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  133.22 + * Other names may be trademarks of their respective owners.
  133.23   *
  133.24 - * You should have received a copy of the GNU General Public License
  133.25 - * along with this program. Look for COPYING file in the top folder.
  133.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  133.27 + * The contents of this file are subject to the terms of either the GNU
  133.28 + * General Public License Version 2 only ("GPL") or the Common
  133.29 + * Development and Distribution License("CDDL") (collectively, the
  133.30 + * "License"). You may not use this file except in compliance with the
  133.31 + * License. You can obtain a copy of the License at
  133.32 + * http://www.netbeans.org/cddl-gplv2.html
  133.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  133.34 + * specific language governing permissions and limitations under the
  133.35 + * License.  When distributing the software, include this License Header
  133.36 + * Notice in each file and include the License file at
  133.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  133.38 + * particular file as subject to the "Classpath" exception as provided
  133.39 + * by Oracle in the GPL Version 2 section of the License file that
  133.40 + * accompanied this code. If applicable, add the following below the
  133.41 + * License Header, with the fields enclosed by brackets [] replaced by
  133.42 + * your own identifying information:
  133.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  133.44 + *
  133.45 + * Contributor(s):
  133.46 + *
  133.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  133.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  133.49 + *
  133.50 + * If you wish your version of this file to be governed by only the CDDL
  133.51 + * or only the GPL Version 2, indicate your decision by adding
  133.52 + * "[Contributor] elects to include this software in this distribution
  133.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  133.54 + * single choice of license, a recipient has the option to distribute
  133.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  133.56 + * to extend the choice of license to its licensees as provided above.
  133.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  133.58 + * Version 2 license, then the option applies only if the new code is
  133.59 + * made subject to such option by the copyright holder.
  133.60   */
  133.61 -
  133.62  package org.apidesign.html.json.spi;
  133.63  
  133.64  import java.io.IOException;
  133.65  import java.io.OutputStream;
  133.66  import net.java.html.BrwsrCtx;
  133.67 -import org.apidesign.html.json.impl.JSON;
  133.68 -import org.apidesign.html.json.impl.RcvrJSON;
  133.69 +import org.netbeans.html.json.impl.JSON;
  133.70 +import org.netbeans.html.json.impl.RcvrJSON;
  133.71  
  133.72  /** Description of a JSON call request that is supposed to be processed
  133.73   * by {@link Transfer#loadJSON(org.apidesign.html.json.spi.JSONCall)} implementors.
   134.1 --- a/json/src/main/java/org/apidesign/html/json/spi/PropertyBinding.java	Thu Dec 19 17:11:01 2013 +0100
   134.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/PropertyBinding.java	Tue Jan 07 08:21:57 2014 +0100
   134.3 @@ -1,77 +1,168 @@
   134.4  /**
   134.5 - * HTML via Java(tm) Language Bindings
   134.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   134.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   134.8   *
   134.9 - * This program is free software: you can redistribute it and/or modify
  134.10 - * it under the terms of the GNU General Public License as published by
  134.11 - * the Free Software Foundation, version 2 of the License.
  134.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  134.13   *
  134.14 - * This program is distributed in the hope that it will be useful,
  134.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  134.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  134.17 - * GNU General Public License for more details. apidesign.org
  134.18 - * designates this particular file as subject to the
  134.19 - * "Classpath" exception as provided by apidesign.org
  134.20 - * in the License file that accompanied this code.
  134.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  134.22 + * Other names may be trademarks of their respective owners.
  134.23   *
  134.24 - * You should have received a copy of the GNU General Public License
  134.25 - * along with this program. Look for COPYING file in the top folder.
  134.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  134.27 + * The contents of this file are subject to the terms of either the GNU
  134.28 + * General Public License Version 2 only ("GPL") or the Common
  134.29 + * Development and Distribution License("CDDL") (collectively, the
  134.30 + * "License"). You may not use this file except in compliance with the
  134.31 + * License. You can obtain a copy of the License at
  134.32 + * http://www.netbeans.org/cddl-gplv2.html
  134.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  134.34 + * specific language governing permissions and limitations under the
  134.35 + * License.  When distributing the software, include this License Header
  134.36 + * Notice in each file and include the License file at
  134.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  134.38 + * particular file as subject to the "Classpath" exception as provided
  134.39 + * by Oracle in the GPL Version 2 section of the License file that
  134.40 + * accompanied this code. If applicable, add the following below the
  134.41 + * License Header, with the fields enclosed by brackets [] replaced by
  134.42 + * your own identifying information:
  134.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  134.44 + *
  134.45 + * Contributor(s):
  134.46 + *
  134.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  134.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  134.49 + *
  134.50 + * If you wish your version of this file to be governed by only the CDDL
  134.51 + * or only the GPL Version 2, indicate your decision by adding
  134.52 + * "[Contributor] elects to include this software in this distribution
  134.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  134.54 + * single choice of license, a recipient has the option to distribute
  134.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  134.56 + * to extend the choice of license to its licensees as provided above.
  134.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  134.58 + * Version 2 license, then the option applies only if the new code is
  134.59 + * made subject to such option by the copyright holder.
  134.60   */
  134.61  package org.apidesign.html.json.spi;
  134.62  
  134.63  import net.java.html.BrwsrCtx;
  134.64 -import org.apidesign.html.json.impl.PropertyBindingAccessor;
  134.65 -import org.apidesign.html.json.impl.PropertyBindingAccessor.PBData;
  134.66 -import org.apidesign.html.json.impl.RcvrJSON;
  134.67 -import org.apidesign.html.json.impl.WrapperObject;
  134.68 +import org.netbeans.html.json.impl.Bindings;
  134.69 +import org.netbeans.html.json.impl.JSON;
  134.70 +import org.netbeans.html.json.impl.PropertyBindingAccessor;
  134.71 +import org.netbeans.html.json.impl.RcvrJSON;
  134.72  
  134.73  /** Describes a property when one is asked to 
  134.74   * bind it 
  134.75   *
  134.76   * @author Jaroslav Tulach <jtulach@netbeans.org>
  134.77   */
  134.78 -public final class PropertyBinding {
  134.79 -    private final PBData<?> data;
  134.80 -    
  134.81 -    private PropertyBinding(PBData<?> p) {
  134.82 -        this.data = p;
  134.83 +public abstract class PropertyBinding {
  134.84 +    PropertyBinding() {
  134.85      }
  134.86  
  134.87      static {
  134.88          new PropertyBindingAccessor() {
  134.89              @Override
  134.90 -            protected <M> PropertyBinding newBinding(PBData<M> d) {
  134.91 -                return new PropertyBinding(d);
  134.92 +            protected JSONCall newCall(BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter, String method, Object data) {
  134.93 +                return new JSONCall(ctx, callback, urlBefore, urlAfter, method, data);
  134.94              }
  134.95  
  134.96              @Override
  134.97 -            protected <M> FunctionBinding newFunction(FBData<M> d) {
  134.98 -                return new FunctionBinding(d);
  134.99 +            protected Bindings bindings(Proto proto, boolean initialize) {
 134.100 +                return initialize ? proto.initBindings() : proto.getBindings();
 134.101              }
 134.102  
 134.103              @Override
 134.104 -            protected JSONCall newCall(BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter, String method, Object data) {
 134.105 -                return new JSONCall(ctx, callback, urlBefore, urlAfter, method, data);
 134.106 +            protected void notifyChange(Proto proto, int propIndex) {
 134.107 +                proto.onChange(propIndex);
 134.108 +            }
 134.109 +
 134.110 +            @Override
 134.111 +            protected Proto findProto(Proto.Type<?> type, Object object) {
 134.112 +                return type.protoFor(object);
 134.113 +            }
 134.114 +
 134.115 +            @Override
 134.116 +            protected <Model> Model cloneTo(Proto.Type<Model> type, Model model, BrwsrCtx c) {
 134.117 +                return type.cloneTo(model, c);
 134.118 +            }
 134.119 +
 134.120 +            @Override
 134.121 +            protected Object read(Proto.Type<?> from, BrwsrCtx c, Object data) {
 134.122 +                return from.read(c, data);
 134.123 +            }
 134.124 +
 134.125 +            @Override
 134.126 +            protected <M> PropertyBinding newBinding(
 134.127 +                Proto.Type<M> access, Bindings<?> bindings, String name,
 134.128 +                int index, M model, boolean readOnly
 134.129 +            ) {
 134.130 +                return new Impl(bindings, name, index, model, access, readOnly);
 134.131              }
 134.132          };
 134.133      }
 134.134  
 134.135 -    public String getPropertyName() {
 134.136 -        return data.name;
 134.137 -    }
 134.138 +    /** Name of the property this binding represents.
 134.139 +     * @return name of the property
 134.140 +     */
 134.141 +    public abstract String getPropertyName();
 134.142  
 134.143 -    public void setValue(Object v) {
 134.144 -        data.setValue(v);
 134.145 -    }
 134.146 +    /** Changes value of the property. Can be called only on dedicated
 134.147 +     * thread. See {@link Technology#runSafe(java.lang.Runnable)}.
 134.148 +     * 
 134.149 +     * @param v new value of the property
 134.150 +     */
 134.151 +    public abstract void setValue(Object v);
 134.152      
 134.153 -    public Object getValue() {
 134.154 -        Object v = data.getValue();
 134.155 -        Object r = WrapperObject.find(v, data.getBindings());
 134.156 -        return r == null ? v : r;
 134.157 -    }
 134.158 +    /** Obtains current value of the property this binding represents.
 134.159 +     * Can be called only on dedicated
 134.160 +     * thread. See {@link Technology#runSafe(java.lang.Runnable)}.
 134.161 +     * 
 134.162 +     * @return the value or <code>null</code>
 134.163 +     */
 134.164 +    public abstract Object getValue();
 134.165      
 134.166 -    public boolean isReadOnly() {
 134.167 -        return data.isReadOnly();
 134.168 -    }
 134.169 +    /** Is this property read only? Or can one call {@link #setValue(java.lang.Object)}?
 134.170 +     * 
 134.171 +     * @return true, if this property is read only
 134.172 +     */
 134.173 +    public abstract boolean isReadOnly();
 134.174 +    
 134.175 +    private static final class Impl<M> extends PropertyBinding {
 134.176 +        public final String name;
 134.177 +        public final boolean readOnly;
 134.178 +        private final M model;
 134.179 +        private final Proto.Type<M> access;
 134.180 +        private final Bindings<?> bindings;
 134.181 +        private final int index;
 134.182 +
 134.183 +        public Impl(Bindings<?> bindings, String name, int index, M model, Proto.Type<M> access, boolean readOnly) {
 134.184 +            this.bindings = bindings;
 134.185 +            this.name = name;
 134.186 +            this.index = index;
 134.187 +            this.model = model;
 134.188 +            this.access = access;
 134.189 +            this.readOnly = readOnly;
 134.190 +        }
 134.191 +
 134.192 +        @Override
 134.193 +        public void setValue(Object v) {
 134.194 +            access.setValue(model, index, v);
 134.195 +        }
 134.196 +
 134.197 +        @Override
 134.198 +        public Object getValue() {
 134.199 +            Object v = access.getValue(model, index);
 134.200 +            Object r = JSON.find(v, bindings);
 134.201 +            return r == null ? v : r;
 134.202 +        }
 134.203 +
 134.204 +        @Override
 134.205 +        public boolean isReadOnly() {
 134.206 +            return readOnly;
 134.207 +        }
 134.208 +
 134.209 +        @Override
 134.210 +        public String getPropertyName() {
 134.211 +            return name;
 134.212 +        }
 134.213 +    } // end of PBData
 134.214 +    
 134.215  }
   135.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   135.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/Proto.java	Tue Jan 07 08:21:57 2014 +0100
   135.3 @@ -0,0 +1,660 @@
   135.4 +/**
   135.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   135.6 + *
   135.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   135.8 + *
   135.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  135.10 + * Other names may be trademarks of their respective owners.
  135.11 + *
  135.12 + * The contents of this file are subject to the terms of either the GNU
  135.13 + * General Public License Version 2 only ("GPL") or the Common
  135.14 + * Development and Distribution License("CDDL") (collectively, the
  135.15 + * "License"). You may not use this file except in compliance with the
  135.16 + * License. You can obtain a copy of the License at
  135.17 + * http://www.netbeans.org/cddl-gplv2.html
  135.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  135.19 + * specific language governing permissions and limitations under the
  135.20 + * License.  When distributing the software, include this License Header
  135.21 + * Notice in each file and include the License file at
  135.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  135.23 + * particular file as subject to the "Classpath" exception as provided
  135.24 + * by Oracle in the GPL Version 2 section of the License file that
  135.25 + * accompanied this code. If applicable, add the following below the
  135.26 + * License Header, with the fields enclosed by brackets [] replaced by
  135.27 + * your own identifying information:
  135.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  135.29 + *
  135.30 + * Contributor(s):
  135.31 + *
  135.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  135.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  135.34 + *
  135.35 + * If you wish your version of this file to be governed by only the CDDL
  135.36 + * or only the GPL Version 2, indicate your decision by adding
  135.37 + * "[Contributor] elects to include this software in this distribution
  135.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  135.39 + * single choice of license, a recipient has the option to distribute
  135.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  135.41 + * to extend the choice of license to its licensees as provided above.
  135.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  135.43 + * Version 2 license, then the option applies only if the new code is
  135.44 + * made subject to such option by the copyright holder.
  135.45 + */
  135.46 +package org.apidesign.html.json.spi;
  135.47 +
  135.48 +import java.util.Collection;
  135.49 +import java.util.List;
  135.50 +import net.java.html.BrwsrCtx;
  135.51 +import net.java.html.json.ComputedProperty;
  135.52 +import net.java.html.json.Model;
  135.53 +import org.netbeans.html.json.impl.Bindings;
  135.54 +import org.netbeans.html.json.impl.JSON;
  135.55 +import org.netbeans.html.json.impl.JSONList;
  135.56 +import org.netbeans.html.json.impl.RcvrJSON;
  135.57 +import org.netbeans.html.json.impl.RcvrJSON.MsgEvnt;
  135.58 +
  135.59 +/** Object associated with one instance of a model generated by the
  135.60 + * {@link Model} annotation. Contains methods the generated class can
  135.61 + * use to communicate with behind the scene associated {@link Technology}.
  135.62 + * Each {@link Proto} object is associated with <a href="http://wiki.apidesign.org/wiki/Singletonizer">
  135.63 + * singletonizer</a>-like interface {@link Type} which provides the 
  135.64 + * associated {@link Technology} the necessary information about the 
  135.65 + * generated {@link Model} class.
  135.66 + *
  135.67 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  135.68 + * @since 0.7
  135.69 + */
  135.70 +public final class Proto {
  135.71 +    private final Object obj;
  135.72 +    private final Type type;
  135.73 +    private final net.java.html.BrwsrCtx context;
  135.74 +    private boolean locked;
  135.75 +    private org.netbeans.html.json.impl.Bindings ko;
  135.76 +
  135.77 +    Proto(Object obj, Type type, BrwsrCtx context) {
  135.78 +        this.obj = obj;
  135.79 +        this.type = type;
  135.80 +        this.context = context;
  135.81 +    }
  135.82 +
  135.83 +    /** Browser context this proto object and its associated model
  135.84 +     * are operating-in.
  135.85 +     * 
  135.86 +     * @return the associated context 
  135.87 +     */
  135.88 +    public BrwsrCtx getContext() {
  135.89 +        return context;
  135.90 +    }
  135.91 +
  135.92 +    /** Before doing modification of the model properties, the
  135.93 +     * generated code enters write lock by calling this method.
  135.94 +     * @throws IllegalStateException if already locked
  135.95 +     */
  135.96 +    public void acquireLock() throws IllegalStateException {
  135.97 +        if (locked) throw new IllegalStateException();
  135.98 +        locked = true;
  135.99 +    }
 135.100 +    
 135.101 +    /** Verifies the model is not locked otherwise throws an exception.
 135.102 +     * @throws IllegalStateException if the model is locked
 135.103 +     */
 135.104 +    public void verifyUnlocked() throws IllegalStateException {
 135.105 +        if (locked) throw new IllegalStateException();
 135.106 +    }
 135.107 +    
 135.108 +    /** When modifications are over, the model is switched into 
 135.109 +     * unlocked state by calling this method.
 135.110 +     */
 135.111 +    public void releaseLock() {
 135.112 +        locked = false;
 135.113 +    }
 135.114 +    
 135.115 +    /** Whenever model changes a property. It should notify the
 135.116 +     * associated technology by calling this method.
 135.117 +     * 
 135.118 +     *@param propName name of the changed property
 135.119 +     */
 135.120 +    public void valueHasMutated(String propName) {
 135.121 +        if (ko != null) {
 135.122 +            ko.valueHasMutated(propName);
 135.123 +        }
 135.124 +    }
 135.125 +    
 135.126 +    /** Initializes the associated model in the current {@link #getContext() context}.
 135.127 +     * In case of <em>knockout.js</em> technology, applies given bindings 
 135.128 +     * of the current model to the <em>body</em> element of the page.
 135.129 +     */
 135.130 +    public void applyBindings() {
 135.131 +        initBindings().applyBindings();
 135.132 +    }
 135.133 +    
 135.134 +    /** Invokes the provided runnable in the {@link #getContext() context}
 135.135 +     * of the browser. If the caller is already on the right thread, the
 135.136 +     * <code>run.run()</code> is invoked immediately and synchronously. 
 135.137 +     * Otherwise the method returns immediately and the <code>run()</code>
 135.138 +     * method is performed later
 135.139 +     * 
 135.140 +     * @param run the action to execute
 135.141 +     */
 135.142 +    public void runInBrowser(Runnable run) {
 135.143 +        JSON.runInBrowser(context, run);
 135.144 +    }
 135.145 +
 135.146 +    /** Initializes the provided collection with a content of the <code>array</code>.
 135.147 +     * The initialization can only be done soon after the the collection 
 135.148 +     * is created, otherwise an exception is throw
 135.149 +     * 
 135.150 +     * @param to the collection to initialize (assumed to be empty)
 135.151 +     * @param array the array to add to the collection
 135.152 +     * @throws IllegalStateException if the system has already been initialized
 135.153 +     */
 135.154 +    public void initTo(Collection<?> to, Object array) {
 135.155 +        if (ko != null) {
 135.156 +            throw new IllegalStateException();
 135.157 +        }
 135.158 +        if (to instanceof JSONList) {
 135.159 +           ((JSONList)to).init(array);
 135.160 +        } else {
 135.161 +            JSONList.init(to, array);
 135.162 +        }
 135.163 +    }
 135.164 +
 135.165 +    /** Takes an object representing JSON result and extract some of its
 135.166 +     * properties. It is assumed that the <code>props</code> and
 135.167 +     * <code>values</code> arrays have the same length.
 135.168 +     * 
 135.169 +     * @param json the JSON object (actual type depends on the associated
 135.170 +     *   {@link Technology})
 135.171 +     * @param props list of properties to extract
 135.172 +     * @param values array that will be filled with extracted values
 135.173 +     */
 135.174 +    public void extract(Object json, String[] props, Object[] values) {
 135.175 +        JSON.extract(context, json, props, values);
 135.176 +    }
 135.177 +
 135.178 +    /** Converts raw JSON <code>data</code> into a Java {@link Model} class.
 135.179 +     * 
 135.180 +     * @param <T> type of the model class
 135.181 +     * @param modelClass the type of the class to create
 135.182 +     * @param data the raw JSON data
 135.183 +     * @return newly created instance of the model class
 135.184 +     */
 135.185 +    public <T> T read(Class<T> modelClass, Object data) {
 135.186 +        return JSON.read(context, modelClass, data);
 135.187 +    }
 135.188 +
 135.189 +    /** Initializes asynchronous JSON connection to specified URL. The 
 135.190 +     * method returns immediately and later does callback later.
 135.191 +     * 
 135.192 +     * @param index the callback index to be used when a reply is received
 135.193 +     *   to call {@link Type#onMessage(java.lang.Object, int, int, java.lang.Object)}.
 135.194 +     * 
 135.195 +     * @param urlBefore the part of the URL before JSON-P callback parameter
 135.196 +     * @param urlAfter the rest of the URL or <code>null</code> if no JSON-P is used
 135.197 +     * @param method method to use for connection to the server
 135.198 +     * @param data string, number or a {@link Model} generated class to send to
 135.199 +     *    the server when doing a query
 135.200 +     */
 135.201 +    public void loadJSON(final int index, 
 135.202 +        String urlBefore, String urlAfter, String method,
 135.203 +        final Object data
 135.204 +    ) {
 135.205 +        class Rcvr extends RcvrJSON {
 135.206 +            @Override
 135.207 +            protected void onMessage(MsgEvnt msg) {
 135.208 +                type.onMessage(obj, index, 1, msg.getValues());
 135.209 +            }
 135.210 +
 135.211 +            @Override
 135.212 +            protected void onError(MsgEvnt msg) {
 135.213 +                type.onMessage(obj, index, 2, msg.getException());
 135.214 +            }
 135.215 +        }
 135.216 +        JSON.loadJSON(context, new Rcvr(), urlBefore, urlAfter, method, data);
 135.217 +    }
 135.218 +    
 135.219 +    /** Opens new WebSocket connection to the specified URL. 
 135.220 +     * 
 135.221 +     * @param index the index to use later during callbacks to 
 135.222 +     *   {@link Type#onMessage(java.lang.Object, int, int, java.lang.Object)}
 135.223 +     * @param url the <code>ws://</code> or <code>wss://</code> URL to connect to
 135.224 +     * @param data data to send to server (usually <code>null</code>)
 135.225 +     * @return returns a non-null object representing the socket
 135.226 +     *   which can be used when calling {@link #wsSend(java.lang.Object, java.lang.String, java.lang.Object) }
 135.227 +     */
 135.228 +    public Object wsOpen(final int index, String url, Object data) {
 135.229 +        class WSrcvr extends RcvrJSON {
 135.230 +            @Override
 135.231 +            protected void onError(MsgEvnt msg) {
 135.232 +                type.onMessage(obj, index, 2, msg.getException());
 135.233 +            }
 135.234 +            
 135.235 +            @Override
 135.236 +            protected void onMessage(MsgEvnt msg) {
 135.237 +                type.onMessage(obj, index, 1, msg.getValues());
 135.238 +            }
 135.239 +            
 135.240 +            @Override
 135.241 +            protected void onClose(MsgEvnt msg) {
 135.242 +                type.onMessage(obj, index, 3, null);
 135.243 +            }
 135.244 +
 135.245 +            @Override
 135.246 +            protected void onOpen(MsgEvnt msg) {
 135.247 +                type.onMessage(obj, index, 0, null);
 135.248 +            }
 135.249 +        }
 135.250 +        return JSON.openWS(context, new WSrcvr(), url, data);
 135.251 +    }
 135.252 +    
 135.253 +    /** Sends a message to existing socket.
 135.254 +     * 
 135.255 +     * @param webSocket the socket to send message to
 135.256 +     * @param url the <code>ws://</code> or <code>wss://</code> URL to connect to,
 135.257 +     *    preferably the same as the one used when the socket was 
 135.258 +     *    {@link #wsOpen(int, java.lang.String, java.lang.Object) opened}
 135.259 +     * @param data the data to send or <code>null</code> if the socket is
 135.260 +     *    supposed to be closed
 135.261 +     */
 135.262 +    public void wsSend(Object webSocket, String url, Object data) {
 135.263 +        ((JSON.WS)webSocket).send(context, url, data);
 135.264 +    }
 135.265 +
 135.266 +    /** Converts raw data (one of its properties) to string representation.
 135.267 +     * 
 135.268 +     * @param data the object
 135.269 +     * @param propName the name of object property or <code>null</code>
 135.270 +     *   if the whole object should be converted
 135.271 +     * @return the string representation of the object or its property
 135.272 +     */
 135.273 +    public String toString(Object data, String propName) {
 135.274 +        return JSON.toString(context, data, propName);
 135.275 +    }
 135.276 +    
 135.277 +    /** Converts raw data (one of its properties) to a number representation.
 135.278 +     * 
 135.279 +     * @param data the object
 135.280 +     * @param propName the name of object property or <code>null</code>
 135.281 +     *   if the whole object should be converted
 135.282 +     * @return the number representation of the object or its property
 135.283 +     */
 135.284 +    public Number toNumber(Object data, String propName) {
 135.285 +        return JSON.toNumber(context, data, propName);
 135.286 +    }
 135.287 +
 135.288 +    /** Converts raw JSON data into a {@link Model} class representation.
 135.289 +     * 
 135.290 +     * @param <T> type of the model to create
 135.291 +     * @param type class of the model to create
 135.292 +     * @param data raw JSON data (depends on associated {@link Technology})
 135.293 +     * @return new instances of the model class filled with values from the
 135.294 +     *   <code>data</code> object
 135.295 +     */
 135.296 +    public <T> T toModel(Class<T> type, Object data) {
 135.297 +        return JSON.toModel(context, type, data, null);
 135.298 +    }
 135.299 +
 135.300 +    /** Creates new JSON like observable list.
 135.301 +     * 
 135.302 +     * @param <T> the type of the list elements
 135.303 +     * @param propName name of a property this list is associated with
 135.304 +     * @param onChange index of the property to use when the list is modified
 135.305 +     *   during callback to {@link Type#onChange(java.lang.Object, int)}
 135.306 +     * @param dependingProps the array of {@link ComputedProperty derived properties}
 135.307 +     *   that depend on the value of the list
 135.308 +     * @return new, empty list associated with this proto-object and its model
 135.309 +     */
 135.310 +    public <T> List<T> createList(String propName, int onChange, String... dependingProps) {
 135.311 +        return new JSONList<T>(this, propName, onChange, dependingProps);
 135.312 +    }
 135.313 +
 135.314 +    /** Copies content of one collection to another, re-assigning all its
 135.315 +     * elements from their current context to the new <code>ctx</code>.
 135.316 +     * 
 135.317 +     * @param <T> type of the collections
 135.318 +     * @param to the target collection to be filled with cloned values
 135.319 +     * @param ctx context for the new collection
 135.320 +     * @param from original collection with its data
 135.321 +     */
 135.322 +    public <T> void cloneList(Collection<T> to, BrwsrCtx ctx, Collection<T> from) {
 135.323 +        Boolean isModel = null;
 135.324 +        for (T t : from) {
 135.325 +            if (isModel == null) {
 135.326 +                isModel = JSON.isModel(t.getClass());
 135.327 +            }
 135.328 +            if (isModel) {
 135.329 +                to.add(JSON.bindTo(t, ctx));
 135.330 +            } else {
 135.331 +                to.add(t);
 135.332 +            }
 135.333 +        }
 135.334 +    }
 135.335 +    
 135.336 +    //
 135.337 +    // internal state
 135.338 +    //
 135.339 +    
 135.340 +    
 135.341 +    final Bindings initBindings() {
 135.342 +        if (ko == null) {
 135.343 +            Bindings b = Bindings.apply(context, obj);
 135.344 +            PropertyBinding[] pb = new PropertyBinding[type.propertyNames.length];
 135.345 +            for (int i = 0; i < pb.length; i++) {
 135.346 +                pb[i] = b.registerProperty(
 135.347 +                    type.propertyNames[i], i, obj, type, type.propertyReadOnly[i]
 135.348 +                );
 135.349 +            }
 135.350 +            FunctionBinding[] fb = new FunctionBinding[type.functions.length];
 135.351 +            for (int i = 0; i < fb.length; i++) {
 135.352 +                fb[i] = FunctionBinding.registerFunction(
 135.353 +                    type.functions[i], i, obj, type
 135.354 +                );
 135.355 +            }
 135.356 +            ko = b;
 135.357 +            b.finish(obj, pb, fb);
 135.358 +        }
 135.359 +        return ko;
 135.360 +    }
 135.361 +
 135.362 +    final Bindings getBindings() {
 135.363 +        return ko;
 135.364 +    }
 135.365 +
 135.366 +    final void onChange(int index) {
 135.367 +        type.onChange(obj, index);
 135.368 +    }
 135.369 +
 135.370 +    /** Functionality used by the code generated by annotation
 135.371 +     * processor for the {@link net.java.html.json.Model} annotation.
 135.372 +     * 
 135.373 +     * @param <Model> the generated class
 135.374 +     * @since 0.7
 135.375 +     */
 135.376 +    public static abstract class Type<Model> {
 135.377 +        private final Class<Model> clazz;
 135.378 +        private final String[] propertyNames;
 135.379 +        private final boolean[] propertyReadOnly;
 135.380 +        private final String[] functions;
 135.381 +
 135.382 +        /** Constructor for subclasses generated by the annotation processor
 135.383 +         * associated with {@link net.java.html.json.Model} annotation.
 135.384 +         * 
 135.385 +         * @param clazz the generated model class
 135.386 +         * @param modelFor the original class annotated by the {@link net.java.html.json.Model} annotation.
 135.387 +         * @param properties number of properties the class has
 135.388 +         * @param functions  number of functions the class has
 135.389 +         */
 135.390 +        protected Type(
 135.391 +            Class<Model> clazz, Class<?> modelFor, int properties, int functions
 135.392 +        ) {
 135.393 +            assert getClass().getName().endsWith("$Html4JavaType");
 135.394 +            try {
 135.395 +                assert getClass().getDeclaringClass() == clazz;
 135.396 +            } catch (SecurityException ex) {
 135.397 +                // OK, no check
 135.398 +            }
 135.399 +            this.clazz = clazz;
 135.400 +            this.propertyNames = new String[properties];
 135.401 +            this.propertyReadOnly = new boolean[properties];
 135.402 +            this.functions = new String[functions];
 135.403 +            JSON.register(clazz, this);
 135.404 +        }
 135.405 +
 135.406 +        /** Registers property for the type. It is expected each index
 135.407 +         * is initialized only once.
 135.408 +         * 
 135.409 +         * @param name name of the property
 135.410 +         * @param index index of the property
 135.411 +         * @param readOnly is the property read only?
 135.412 +         */
 135.413 +        protected final void registerProperty(String name, int index, boolean readOnly) {
 135.414 +            assert propertyNames[index] == null;
 135.415 +            propertyNames[index] = name;
 135.416 +            propertyReadOnly[index] = readOnly;
 135.417 +        }
 135.418 +
 135.419 +        /** Registers function of given name at given index.
 135.420 +         * 
 135.421 +         * @param name name of the function
 135.422 +         * @param index name of the type
 135.423 +         */
 135.424 +        protected final void registerFunction(String name, int index) {
 135.425 +            assert functions[index] == null;
 135.426 +            functions[index] = name;
 135.427 +        }
 135.428 +        
 135.429 +        /** Creates new proto-object for given {@link Model} class bound to
 135.430 +         * provided context.
 135.431 +         * 
 135.432 +         * @param obj instance of appropriate {@link Model} class
 135.433 +         * @param context the browser context
 135.434 +         * @return new proto-object that the generated class can use for
 135.435 +         *   communication with the infrastructure
 135.436 +         */
 135.437 +        public Proto createProto(Object obj, BrwsrCtx context) {
 135.438 +            return new Proto(obj, this, context);
 135.439 +        }
 135.440 +        
 135.441 +        //
 135.442 +        // Implemented by subclasses
 135.443 +        //
 135.444 +        
 135.445 +        /** Sets value of a {@link #registerProperty(java.lang.String, int, boolean) registered property}
 135.446 +         * to new value.
 135.447 +         * 
 135.448 +         * @param model the instance of {@link Model model class}
 135.449 +         * @param index index of the property used during registration
 135.450 +         * @param value the value to set the property to
 135.451 +         */
 135.452 +        protected abstract void setValue(Model model, int index, Object value);
 135.453 +        
 135.454 +        /** Obtains and returns value of a 
 135.455 +         * {@link #registerProperty(java.lang.String, int, boolean) registered property}.
 135.456 +         * 
 135.457 +         * @param model the instance of {@link Model model class}
 135.458 +         * @param index index of the property used during registration
 135.459 +         * @return current value of the property
 135.460 +         */
 135.461 +        protected abstract Object getValue(Model model, int index);
 135.462 +        
 135.463 +        /** Invokes a {@link #registerFunction(java.lang.String, int)} registered function
 135.464 +         * on given object.
 135.465 +         * 
 135.466 +         * @param model the instance of {@link Model model class}
 135.467 +         * @param index index of the property used during registration
 135.468 +         * @param data the currently selected object the function is about to operate on
 135.469 +         * @param event the event that triggered the event
 135.470 +         */
 135.471 +        protected abstract void call(Model model, int index, Object data, Object event);
 135.472 +        
 135.473 +        /** Re-binds the model object to new browser context.
 135.474 +         * 
 135.475 +         * @param model the instance of {@link Model model class}
 135.476 +         * @param ctx browser context to clone the object to
 135.477 +         * @return new instance of the model suitable for new context
 135.478 +         */
 135.479 +        protected abstract Model cloneTo(Model model, BrwsrCtx ctx);
 135.480 +        
 135.481 +        /** Reads raw JSON data and converts them to our model class.
 135.482 +         * 
 135.483 +         * @param c the browser context to work in
 135.484 +         * @param json raw JSON data to get values from
 135.485 +         * @return new instance of model class filled by the data
 135.486 +         */
 135.487 +        protected abstract Model read(BrwsrCtx c, Object json);
 135.488 +        
 135.489 +        /** Called when a {@link #registerProperty(java.lang.String, int, boolean) registered property}
 135.490 +         * changes its value.
 135.491 +         * 
 135.492 +         * @param model the object that has the property
 135.493 +         * @param index the index of the property during registration
 135.494 +         */
 135.495 +        protected abstract void onChange(Model model, int index);
 135.496 +        
 135.497 +        /** Finds out if there is an associated proto-object for given
 135.498 +         * object.
 135.499 +         * 
 135.500 +         * @param object an object, presumably (but not necessarily) instance of Model class
 135.501 +         * @return associated proto-object or <code>null</code>
 135.502 +         */
 135.503 +        protected abstract Proto protoFor(Object object);
 135.504 +
 135.505 +        /** Called to report results of asynchronous over-the-wire 
 135.506 +         * communication. Result of calling {@link Proto#wsOpen(int, java.lang.String, java.lang.Object)}
 135.507 +         * or {@link Proto#loadJSON(int, java.lang.String, java.lang.String, java.lang.String, java.lang.Object)}.
 135.508 +         * 
 135.509 +         * @param model the instance of the model class
 135.510 +         * @param index index used during initiating the communication (via <code>loadJSON</code> or <code>wsOpen</code> calls)
 135.511 +         * @param type type of the message: 0 - onOpen, 1 - onMessage, 2 - onError, 3 - onClose -
 135.512 +         *   not all messages are applicable to all communication protocols (JSON has only 1 and 2).
 135.513 +         * @param data <code>null</code> or string, number or a {@link Model} class
 135.514 +         *   obtained to the server as a response
 135.515 +         */
 135.516 +        protected abstract void onMessage(Model model, int index, int type, Object data);
 135.517 +
 135.518 +        //
 135.519 +        // Various support methods the generated classes use
 135.520 +        //
 135.521 +
 135.522 +        /** Converts and array of raw JSON objects into an array of typed
 135.523 +         * Java {@lin Model} classes.
 135.524 +         * 
 135.525 +         * @param <T> the type of the destination array
 135.526 +         * @param context browser context to use
 135.527 +         * @param src array of raw JSON objects
 135.528 +         * @param destType type of the individual array elements
 135.529 +         * @param dest array to be filled with read type instances
 135.530 +         */
 135.531 +        public <T> void copyJSON(BrwsrCtx context, Object[] src, Class<T> destType, T[] dest) {
 135.532 +            for (int i = 0; i < src.length && i < dest.length; i++) {
 135.533 +                dest[i] = org.netbeans.html.json.impl.JSON.read(context, destType, src[i]);
 135.534 +            }
 135.535 +        }
 135.536 +        
 135.537 +        /** Compares two objects that can be converted to integers.
 135.538 +         * @return true if they are the same
 135.539 +         */
 135.540 +        public final boolean isSame(int a, int b) {
 135.541 +            return a == b;
 135.542 +        }
 135.543 +
 135.544 +        /** Compares two objects that can be converted to (floating point)
 135.545 +         * numbers.
 135.546 +         * @return  true if they are the same
 135.547 +         */
 135.548 +        public final boolean isSame(double a, double b) {
 135.549 +            return a == b;
 135.550 +        }
 135.551 +
 135.552 +        /** Compares two objects for being the same - e.g. either <code>==</code>
 135.553 +         * or <code>equals</code>.
 135.554 +         * @return true if they are equals
 135.555 +         */ 
 135.556 +        public final boolean isSame(Object a, Object b) {
 135.557 +            if (a == b) {
 135.558 +                return true;
 135.559 +            }
 135.560 +            if (a == null || b == null) {
 135.561 +                return false;
 135.562 +            }
 135.563 +            return a.equals(b);
 135.564 +        }
 135.565 +
 135.566 +        /** Cumulative hash function. Adds hashcode of the object to the
 135.567 +         * previous value.
 135.568 +         * @param o the object (or <code>null</code>)
 135.569 +         * @param h the previous value of the hash
 135.570 +         * @return new hash - the old one xor the object's one
 135.571 +         */
 135.572 +        public final int hashPlus(Object o, int h) {
 135.573 +            return o == null ? h : h ^ o.hashCode();
 135.574 +        }
 135.575 +        
 135.576 +        /** Converts an object to its JSON value.
 135.577 +         * 
 135.578 +         * @param obj the object to convert
 135.579 +         * @return JSON representation of the object
 135.580 +         */
 135.581 +        public final String toJSON(Object obj) {
 135.582 +            return JSON.toJSON(obj);
 135.583 +        }
 135.584 +        
 135.585 +        /** Converts the value to string.
 135.586 +         * 
 135.587 +         * @param val the value
 135.588 +         * @return the converted value
 135.589 +         */
 135.590 +        public final String stringValue(Object val) {
 135.591 +            return JSON.stringValue(val);
 135.592 +        }
 135.593 +
 135.594 +        /** Converts the value to number.
 135.595 +         * 
 135.596 +         * @param val the value
 135.597 +         * @return the converted value
 135.598 +         */
 135.599 +        public final Number numberValue(Object val) {
 135.600 +            return JSON.numberValue(val);
 135.601 +        }
 135.602 +
 135.603 +        /** Converts the value to character.
 135.604 +         * 
 135.605 +         * @param val the value
 135.606 +         * @return the converted value
 135.607 +         */
 135.608 +        public final Character charValue(Object val) {
 135.609 +            return JSON.charValue(val);
 135.610 +        }
 135.611 +
 135.612 +        /** Converts the value to boolean.
 135.613 +         * 
 135.614 +         * @param val the value
 135.615 +         * @return the converted value
 135.616 +         */
 135.617 +        public final Boolean boolValue(Object val) {
 135.618 +            return JSON.boolValue(val);
 135.619 +        }
 135.620 +        
 135.621 +        /** Extracts value of specific type from given object.
 135.622 +         * 
 135.623 +         * @param <T> the type of object one is interested in
 135.624 +         * @param type the type
 135.625 +         * @param val the object to convert to type
 135.626 +         * @return the converted value
 135.627 +         */
 135.628 +        public final <T> T extractValue(Class<T> type, Object val) {
 135.629 +            if (Number.class.isAssignableFrom(type)) {
 135.630 +                val = numberValue(val);
 135.631 +            }
 135.632 +            if (Boolean.class == type) {
 135.633 +                val = boolValue(val);
 135.634 +            }
 135.635 +            if (String.class == type) {
 135.636 +                val = stringValue(val);
 135.637 +            }
 135.638 +            if (Character.class == type) {
 135.639 +                val = charValue(val);
 135.640 +            }
 135.641 +            if (Integer.class == type) {
 135.642 +                val = val instanceof Number ? ((Number) val).intValue() : 0;
 135.643 +            }
 135.644 +            if (Long.class == type) {
 135.645 +                val = val instanceof Number ? ((Number) val).longValue() : 0;
 135.646 +            }
 135.647 +            if (Short.class == type) {
 135.648 +                val = val instanceof Number ? ((Number) val).shortValue() : 0;
 135.649 +            }
 135.650 +            if (Byte.class == type) {
 135.651 +                val = val instanceof Number ? ((Number) val).byteValue() : 0;
 135.652 +            }
 135.653 +            if (Double.class == type) {
 135.654 +                val = val instanceof Number ? ((Number) val).doubleValue() : Double.NaN;
 135.655 +            }
 135.656 +            if (Float.class == type) {
 135.657 +                val = val instanceof Number ? ((Number) val).floatValue() : Float.NaN;
 135.658 +            }
 135.659 +            return type.cast(val);
 135.660 +        }
 135.661 +
 135.662 +    }
 135.663 +}
   136.1 --- a/json/src/main/java/org/apidesign/html/json/spi/Technology.java	Thu Dec 19 17:11:01 2013 +0100
   136.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/Technology.java	Tue Jan 07 08:21:57 2014 +0100
   136.3 @@ -1,22 +1,44 @@
   136.4  /**
   136.5 - * HTML via Java(tm) Language Bindings
   136.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   136.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   136.8   *
   136.9 - * This program is free software: you can redistribute it and/or modify
  136.10 - * it under the terms of the GNU General Public License as published by
  136.11 - * the Free Software Foundation, version 2 of the License.
  136.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  136.13   *
  136.14 - * This program is distributed in the hope that it will be useful,
  136.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  136.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  136.17 - * GNU General Public License for more details. apidesign.org
  136.18 - * designates this particular file as subject to the
  136.19 - * "Classpath" exception as provided by apidesign.org
  136.20 - * in the License file that accompanied this code.
  136.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  136.22 + * Other names may be trademarks of their respective owners.
  136.23   *
  136.24 - * You should have received a copy of the GNU General Public License
  136.25 - * along with this program. Look for COPYING file in the top folder.
  136.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  136.27 + * The contents of this file are subject to the terms of either the GNU
  136.28 + * General Public License Version 2 only ("GPL") or the Common
  136.29 + * Development and Distribution License("CDDL") (collectively, the
  136.30 + * "License"). You may not use this file except in compliance with the
  136.31 + * License. You can obtain a copy of the License at
  136.32 + * http://www.netbeans.org/cddl-gplv2.html
  136.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  136.34 + * specific language governing permissions and limitations under the
  136.35 + * License.  When distributing the software, include this License Header
  136.36 + * Notice in each file and include the License file at
  136.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  136.38 + * particular file as subject to the "Classpath" exception as provided
  136.39 + * by Oracle in the GPL Version 2 section of the License file that
  136.40 + * accompanied this code. If applicable, add the following below the
  136.41 + * License Header, with the fields enclosed by brackets [] replaced by
  136.42 + * your own identifying information:
  136.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  136.44 + *
  136.45 + * Contributor(s):
  136.46 + *
  136.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  136.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  136.49 + *
  136.50 + * If you wish your version of this file to be governed by only the CDDL
  136.51 + * or only the GPL Version 2, indicate your decision by adding
  136.52 + * "[Contributor] elects to include this software in this distribution
  136.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  136.54 + * single choice of license, a recipient has the option to distribute
  136.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  136.56 + * to extend the choice of license to its licensees as provided above.
  136.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  136.58 + * Version 2 license, then the option applies only if the new code is
  136.59 + * made subject to such option by the copyright holder.
  136.60   */
  136.61  package org.apidesign.html.json.spi;
  136.62  
   137.1 --- a/json/src/main/java/org/apidesign/html/json/spi/Transfer.java	Thu Dec 19 17:11:01 2013 +0100
   137.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/Transfer.java	Tue Jan 07 08:21:57 2014 +0100
   137.3 @@ -1,24 +1,45 @@
   137.4  /**
   137.5 - * HTML via Java(tm) Language Bindings
   137.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   137.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   137.8   *
   137.9 - * This program is free software: you can redistribute it and/or modify
  137.10 - * it under the terms of the GNU General Public License as published by
  137.11 - * the Free Software Foundation, version 2 of the License.
  137.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  137.13   *
  137.14 - * This program is distributed in the hope that it will be useful,
  137.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  137.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  137.17 - * GNU General Public License for more details. apidesign.org
  137.18 - * designates this particular file as subject to the
  137.19 - * "Classpath" exception as provided by apidesign.org
  137.20 - * in the License file that accompanied this code.
  137.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  137.22 + * Other names may be trademarks of their respective owners.
  137.23   *
  137.24 - * You should have received a copy of the GNU General Public License
  137.25 - * along with this program. Look for COPYING file in the top folder.
  137.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  137.27 + * The contents of this file are subject to the terms of either the GNU
  137.28 + * General Public License Version 2 only ("GPL") or the Common
  137.29 + * Development and Distribution License("CDDL") (collectively, the
  137.30 + * "License"). You may not use this file except in compliance with the
  137.31 + * License. You can obtain a copy of the License at
  137.32 + * http://www.netbeans.org/cddl-gplv2.html
  137.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  137.34 + * specific language governing permissions and limitations under the
  137.35 + * License.  When distributing the software, include this License Header
  137.36 + * Notice in each file and include the License file at
  137.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  137.38 + * particular file as subject to the "Classpath" exception as provided
  137.39 + * by Oracle in the GPL Version 2 section of the License file that
  137.40 + * accompanied this code. If applicable, add the following below the
  137.41 + * License Header, with the fields enclosed by brackets [] replaced by
  137.42 + * your own identifying information:
  137.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  137.44 + *
  137.45 + * Contributor(s):
  137.46 + *
  137.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  137.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  137.49 + *
  137.50 + * If you wish your version of this file to be governed by only the CDDL
  137.51 + * or only the GPL Version 2, indicate your decision by adding
  137.52 + * "[Contributor] elects to include this software in this distribution
  137.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  137.54 + * single choice of license, a recipient has the option to distribute
  137.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  137.56 + * to extend the choice of license to its licensees as provided above.
  137.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  137.58 + * Version 2 license, then the option applies only if the new code is
  137.59 + * made subject to such option by the copyright holder.
  137.60   */
  137.61 -
  137.62  package org.apidesign.html.json.spi;
  137.63  
  137.64  import java.io.IOException;
   138.1 --- a/json/src/main/java/org/apidesign/html/json/spi/WSTransfer.java	Thu Dec 19 17:11:01 2013 +0100
   138.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/WSTransfer.java	Tue Jan 07 08:21:57 2014 +0100
   138.3 @@ -1,22 +1,44 @@
   138.4  /**
   138.5 - * HTML via Java(tm) Language Bindings
   138.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   138.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   138.8   *
   138.9 - * This program is free software: you can redistribute it and/or modify
  138.10 - * it under the terms of the GNU General Public License as published by
  138.11 - * the Free Software Foundation, version 2 of the License.
  138.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  138.13   *
  138.14 - * This program is distributed in the hope that it will be useful,
  138.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  138.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  138.17 - * GNU General Public License for more details. apidesign.org
  138.18 - * designates this particular file as subject to the
  138.19 - * "Classpath" exception as provided by apidesign.org
  138.20 - * in the License file that accompanied this code.
  138.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  138.22 + * Other names may be trademarks of their respective owners.
  138.23   *
  138.24 - * You should have received a copy of the GNU General Public License
  138.25 - * along with this program. Look for COPYING file in the top folder.
  138.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  138.27 + * The contents of this file are subject to the terms of either the GNU
  138.28 + * General Public License Version 2 only ("GPL") or the Common
  138.29 + * Development and Distribution License("CDDL") (collectively, the
  138.30 + * "License"). You may not use this file except in compliance with the
  138.31 + * License. You can obtain a copy of the License at
  138.32 + * http://www.netbeans.org/cddl-gplv2.html
  138.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  138.34 + * specific language governing permissions and limitations under the
  138.35 + * License.  When distributing the software, include this License Header
  138.36 + * Notice in each file and include the License file at
  138.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  138.38 + * particular file as subject to the "Classpath" exception as provided
  138.39 + * by Oracle in the GPL Version 2 section of the License file that
  138.40 + * accompanied this code. If applicable, add the following below the
  138.41 + * License Header, with the fields enclosed by brackets [] replaced by
  138.42 + * your own identifying information:
  138.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  138.44 + *
  138.45 + * Contributor(s):
  138.46 + *
  138.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  138.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  138.49 + *
  138.50 + * If you wish your version of this file to be governed by only the CDDL
  138.51 + * or only the GPL Version 2, indicate your decision by adding
  138.52 + * "[Contributor] elects to include this software in this distribution
  138.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  138.54 + * single choice of license, a recipient has the option to distribute
  138.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  138.56 + * to extend the choice of license to its licensees as provided above.
  138.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  138.58 + * Version 2 license, then the option applies only if the new code is
  138.59 + * made subject to such option by the copyright holder.
  138.60   */
  138.61  package org.apidesign.html.json.spi;
  138.62  
   139.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   139.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/package.html	Tue Jan 07 08:21:57 2014 +0100
   139.3 @@ -0,0 +1,51 @@
   139.4 +<!--
   139.5 +
   139.6 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   139.7 +
   139.8 +    Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   139.9 +
  139.10 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  139.11 +    Other names may be trademarks of their respective owners.
  139.12 +
  139.13 +    The contents of this file are subject to the terms of either the GNU
  139.14 +    General Public License Version 2 only ("GPL") or the Common
  139.15 +    Development and Distribution License("CDDL") (collectively, the
  139.16 +    "License"). You may not use this file except in compliance with the
  139.17 +    License. You can obtain a copy of the License at
  139.18 +    http://www.netbeans.org/cddl-gplv2.html
  139.19 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  139.20 +    specific language governing permissions and limitations under the
  139.21 +    License.  When distributing the software, include this License Header
  139.22 +    Notice in each file and include the License file at
  139.23 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  139.24 +    particular file as subject to the "Classpath" exception as provided
  139.25 +    by Oracle in the GPL Version 2 section of the License file that
  139.26 +    accompanied this code. If applicable, add the following below the
  139.27 +    License Header, with the fields enclosed by brackets [] replaced by
  139.28 +    your own identifying information:
  139.29 +    "Portions Copyrighted [year] [name of copyright owner]"
  139.30 +
  139.31 +    Contributor(s):
  139.32 +
  139.33 +    The Original Software is NetBeans. The Initial Developer of the Original
  139.34 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  139.35 +
  139.36 +    If you wish your version of this file to be governed by only the CDDL
  139.37 +    or only the GPL Version 2, indicate your decision by adding
  139.38 +    "[Contributor] elects to include this software in this distribution
  139.39 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
  139.40 +    single choice of license, a recipient has the option to distribute
  139.41 +    your version of this file under either the CDDL, the GPL Version 2 or
  139.42 +    to extend the choice of license to its licensees as provided above.
  139.43 +    However, if you add GPL Version 2 code and therefore, elected the GPL
  139.44 +    Version 2 license, then the option applies only if the new code is
  139.45 +    made subject to such option by the copyright holder.
  139.46 +
  139.47 +-->
  139.48 +<html>
  139.49 +    <body>
  139.50 +        <div>Service Provider Interfaces for those who wish to integrate own
  139.51 +            <a href="Technology.html">technology</a> with the HTML for Java API.
  139.52 +        </div>
  139.53 +    </body>
  139.54 +</html>
   140.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   140.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/Bindings.java	Tue Jan 07 08:21:57 2014 +0100
   140.3 @@ -0,0 +1,108 @@
   140.4 +/**
   140.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   140.6 + *
   140.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   140.8 + *
   140.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  140.10 + * Other names may be trademarks of their respective owners.
  140.11 + *
  140.12 + * The contents of this file are subject to the terms of either the GNU
  140.13 + * General Public License Version 2 only ("GPL") or the Common
  140.14 + * Development and Distribution License("CDDL") (collectively, the
  140.15 + * "License"). You may not use this file except in compliance with the
  140.16 + * License. You can obtain a copy of the License at
  140.17 + * http://www.netbeans.org/cddl-gplv2.html
  140.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  140.19 + * specific language governing permissions and limitations under the
  140.20 + * License.  When distributing the software, include this License Header
  140.21 + * Notice in each file and include the License file at
  140.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  140.23 + * particular file as subject to the "Classpath" exception as provided
  140.24 + * by Oracle in the GPL Version 2 section of the License file that
  140.25 + * accompanied this code. If applicable, add the following below the
  140.26 + * License Header, with the fields enclosed by brackets [] replaced by
  140.27 + * your own identifying information:
  140.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  140.29 + *
  140.30 + * Contributor(s):
  140.31 + *
  140.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  140.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  140.34 + *
  140.35 + * If you wish your version of this file to be governed by only the CDDL
  140.36 + * or only the GPL Version 2, indicate your decision by adding
  140.37 + * "[Contributor] elects to include this software in this distribution
  140.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  140.39 + * single choice of license, a recipient has the option to distribute
  140.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  140.41 + * to extend the choice of license to its licensees as provided above.
  140.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  140.43 + * Version 2 license, then the option applies only if the new code is
  140.44 + * made subject to such option by the copyright holder.
  140.45 + */
  140.46 +package org.netbeans.html.json.impl;
  140.47 +
  140.48 +import net.java.html.BrwsrCtx;
  140.49 +import org.apidesign.html.json.spi.FunctionBinding;
  140.50 +import org.apidesign.html.json.spi.PropertyBinding;
  140.51 +import org.apidesign.html.json.spi.Proto;
  140.52 +import org.apidesign.html.json.spi.Technology;
  140.53 +
  140.54 +/**
  140.55 + *
  140.56 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  140.57 + */
  140.58 +public final class Bindings<Data> {
  140.59 +    private Data data;
  140.60 +    private final Technology<Data> bp;
  140.61 +
  140.62 +    private Bindings(Technology<Data> bp) {
  140.63 +        this.bp = bp;
  140.64 +    }
  140.65 +    
  140.66 +    public <M> PropertyBinding registerProperty(String propName, int index, M model, Proto.Type<M> access, boolean readOnly) {
  140.67 +        return PropertyBindingAccessor.create(access, this, propName, index, model, readOnly);
  140.68 +    }
  140.69 +
  140.70 +    public static Bindings<?> apply(BrwsrCtx c, Object model) {
  140.71 +        Technology<?> bp = JSON.findTechnology(c);
  140.72 +        return apply(bp);
  140.73 +    }
  140.74 +    
  140.75 +    private static <Data> Bindings<Data> apply(Technology<Data> bp) {
  140.76 +        return new Bindings<Data>(bp);
  140.77 +    }
  140.78 +    
  140.79 +    public final void finish(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
  140.80 +        assert data == null;
  140.81 +        if (bp instanceof Technology.BatchInit) {
  140.82 +            Technology.BatchInit<Data> bi = (Technology.BatchInit<Data>)bp;
  140.83 +            data = bi.wrapModel(model, propArr, funcArr);
  140.84 +        } else {
  140.85 +            data = bp.wrapModel(model);
  140.86 +            for (PropertyBinding b : propArr) {
  140.87 +                bp.bind(b, model, data);
  140.88 +            }
  140.89 +            for (FunctionBinding b : funcArr) {
  140.90 +                bp.expose(b, model, data);
  140.91 +            }
  140.92 +        }
  140.93 +    }
  140.94 +    
  140.95 +    
  140.96 +    public Data koData() {
  140.97 +        return data;
  140.98 +    }
  140.99 +
 140.100 +    public void valueHasMutated(String firstName) {
 140.101 +        bp.valueHasMutated(data, firstName);
 140.102 +    }
 140.103 +    
 140.104 +    public void applyBindings() {
 140.105 +        bp.applyBindings(data);
 140.106 +    }
 140.107 +
 140.108 +    Object wrapArray(Object[] arr) {
 140.109 +        return bp.wrapArray(arr);
 140.110 +    }
 140.111 +}
   141.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   141.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/JSON.java	Tue Jan 07 08:21:57 2014 +0100
   141.3 @@ -0,0 +1,501 @@
   141.4 +/**
   141.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   141.6 + *
   141.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   141.8 + *
   141.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  141.10 + * Other names may be trademarks of their respective owners.
  141.11 + *
  141.12 + * The contents of this file are subject to the terms of either the GNU
  141.13 + * General Public License Version 2 only ("GPL") or the Common
  141.14 + * Development and Distribution License("CDDL") (collectively, the
  141.15 + * "License"). You may not use this file except in compliance with the
  141.16 + * License. You can obtain a copy of the License at
  141.17 + * http://www.netbeans.org/cddl-gplv2.html
  141.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  141.19 + * specific language governing permissions and limitations under the
  141.20 + * License.  When distributing the software, include this License Header
  141.21 + * Notice in each file and include the License file at
  141.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  141.23 + * particular file as subject to the "Classpath" exception as provided
  141.24 + * by Oracle in the GPL Version 2 section of the License file that
  141.25 + * accompanied this code. If applicable, add the following below the
  141.26 + * License Header, with the fields enclosed by brackets [] replaced by
  141.27 + * your own identifying information:
  141.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  141.29 + *
  141.30 + * Contributor(s):
  141.31 + *
  141.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  141.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  141.34 + *
  141.35 + * If you wish your version of this file to be governed by only the CDDL
  141.36 + * or only the GPL Version 2, indicate your decision by adding
  141.37 + * "[Contributor] elects to include this software in this distribution
  141.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  141.39 + * single choice of license, a recipient has the option to distribute
  141.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  141.41 + * to extend the choice of license to its licensees as provided above.
  141.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  141.43 + * Version 2 license, then the option applies only if the new code is
  141.44 + * made subject to such option by the copyright holder.
  141.45 + */
  141.46 +package org.netbeans.html.json.impl;
  141.47 +
  141.48 +import java.io.IOException;
  141.49 +import java.io.InputStream;
  141.50 +import java.util.Collection;
  141.51 +import java.util.HashMap;
  141.52 +import java.util.Map;
  141.53 +import net.java.html.BrwsrCtx;
  141.54 +import org.apidesign.html.context.spi.Contexts;
  141.55 +import org.apidesign.html.json.spi.FunctionBinding;
  141.56 +import org.apidesign.html.json.spi.JSONCall;
  141.57 +import org.apidesign.html.json.spi.PropertyBinding;
  141.58 +import org.apidesign.html.json.spi.Proto;
  141.59 +import org.apidesign.html.json.spi.Technology;
  141.60 +import org.apidesign.html.json.spi.Transfer;
  141.61 +import org.apidesign.html.json.spi.WSTransfer;
  141.62 +
  141.63 +/**
  141.64 + *
  141.65 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  141.66 + */
  141.67 +public final class JSON {
  141.68 +    private JSON() {
  141.69 +    }
  141.70 +
  141.71 +    static Technology<?> findTechnology(BrwsrCtx c) {
  141.72 +        Technology<?> t = Contexts.find(c, Technology.class);
  141.73 +        return t == null ? EmptyTech.EMPTY : t;
  141.74 +    }
  141.75 +
  141.76 +    static Transfer findTransfer(BrwsrCtx c) {
  141.77 +        Transfer t = Contexts.find(c, Transfer.class);
  141.78 +        return t == null ? EmptyTech.EMPTY : t;
  141.79 +    }
  141.80 +
  141.81 +    static WSTransfer<?> findWSTransfer(BrwsrCtx c) {
  141.82 +        WSTransfer<?> t = Contexts.find(c, WSTransfer.class);
  141.83 +        return t == null ? EmptyTech.EMPTY : t;
  141.84 +    }
  141.85 +    
  141.86 +    public static void runInBrowser(BrwsrCtx c, Runnable runnable) {
  141.87 +        findTechnology(c).runSafe(runnable);
  141.88 +    }
  141.89 +    
  141.90 +    public static void extract(BrwsrCtx c, Object value, String[] props, Object[] values) {
  141.91 +        Transfer t = findTransfer(c);
  141.92 +        t.extract(value, props, values);
  141.93 +    }
  141.94 +    
  141.95 +    private static Object getProperty(BrwsrCtx c, Object obj, String prop) {
  141.96 +        if (prop == null) return obj;
  141.97 +        
  141.98 +        String[] arr = { prop };
  141.99 +        Object[] val = { null };
 141.100 +        extract(c, obj, arr, val);
 141.101 +        return val[0];
 141.102 +    }
 141.103 +
 141.104 +    public static String toJSON(Object value) {
 141.105 +        if (value == null) {
 141.106 +            return "null";
 141.107 +        }
 141.108 +        if (value instanceof Enum) {
 141.109 +            value = value.toString();
 141.110 +        }
 141.111 +        if (value instanceof String) {
 141.112 +            String s = (String)value;
 141.113 +            int len = s.length();
 141.114 +            StringBuilder sb = new StringBuilder(len + 10);
 141.115 +            sb.append('"');
 141.116 +            for (int i = 0; i < len; i++) {
 141.117 +                char ch = s.charAt(i);
 141.118 +                switch (ch) {
 141.119 +                    case '\"': sb.append("\\\""); break;
 141.120 +                    case '\n': sb.append("\\n"); break;
 141.121 +                    case '\r': sb.append("\\r"); break;
 141.122 +                    case '\t': sb.append("\\t"); break;
 141.123 +                    case '\\': sb.append("\\\\"); break;
 141.124 +                    default: sb.append(ch);
 141.125 +                }
 141.126 +            }
 141.127 +            sb.append('"');
 141.128 +            return sb.toString();
 141.129 +        }
 141.130 +        return value.toString();
 141.131 +    }
 141.132 +
 141.133 +    public static String toString(BrwsrCtx c, Object obj, String prop) {
 141.134 +        obj = getProperty(c, obj, prop);
 141.135 +        return obj instanceof String ? (String)obj : null;
 141.136 +    }
 141.137 +    public static Number toNumber(BrwsrCtx c, Object obj, String prop) {
 141.138 +        obj = getProperty(c, obj, prop);
 141.139 +        if (!(obj instanceof Number)) {
 141.140 +            obj = Double.NaN;
 141.141 +        }
 141.142 +        return (Number)obj;
 141.143 +    }
 141.144 +    public static <M> M toModel(BrwsrCtx c, Class<M> aClass, Object data, Object object) {
 141.145 +        Technology<?> t = findTechnology(c);
 141.146 +        Object o = t.toModel(aClass, data);
 141.147 +        return aClass.cast(o);
 141.148 +    }
 141.149 +    
 141.150 +    public static boolean isSame(int a, int b) {
 141.151 +        return a == b;
 141.152 +    }
 141.153 +    
 141.154 +    public static boolean isSame(double a, double b) {
 141.155 +        return a == b;
 141.156 +    }
 141.157 +    
 141.158 +    public static boolean isSame(Object a, Object b) {
 141.159 +        if (a == b) {
 141.160 +            return true;
 141.161 +        }
 141.162 +        if (a == null || b == null) {
 141.163 +            return false;
 141.164 +        }
 141.165 +        return a.equals(b);
 141.166 +    }
 141.167 +    
 141.168 +    public static int hashPlus(Object o, int h) {
 141.169 +        return o == null ? h : h ^ o.hashCode();
 141.170 +    }
 141.171 +
 141.172 +    public static <T> T extractValue(Class<T> type, Object val) {
 141.173 +        if (Number.class.isAssignableFrom(type)) {
 141.174 +            val = numberValue(val);
 141.175 +        }
 141.176 +        if (Boolean.class == type) {
 141.177 +            val = boolValue(val);
 141.178 +        }
 141.179 +        if (String.class == type) {
 141.180 +            val = stringValue(val);
 141.181 +        }
 141.182 +        if (Character.class == type) {
 141.183 +            val = charValue(val);
 141.184 +        }
 141.185 +        if (Integer.class == type) {
 141.186 +            val = val instanceof Number ? ((Number)val).intValue() : 0;
 141.187 +        }
 141.188 +        if (Long.class == type) {
 141.189 +            val = val instanceof Number  ? ((Number)val).longValue() : 0;
 141.190 +        }
 141.191 +        if (Short.class == type) {
 141.192 +            val = val instanceof Number ? ((Number)val).shortValue() : 0;
 141.193 +        }
 141.194 +        if (Byte.class == type) {
 141.195 +            val = val instanceof Number ? ((Number)val).byteValue() : 0;
 141.196 +        }        
 141.197 +        if (Double.class == type) {
 141.198 +            val = val instanceof Number ? ((Number)val).doubleValue() : Double.NaN;
 141.199 +        }
 141.200 +        if (Float.class == type) {
 141.201 +            val = val instanceof Number ? ((Number)val).floatValue() : Float.NaN;
 141.202 +        }
 141.203 +        return type.cast(val);
 141.204 +    }
 141.205 +    
 141.206 +    static boolean isNumeric(Object val) {
 141.207 +        return ((val instanceof Integer) || (val instanceof Long) || (val instanceof Short) || (val instanceof Byte));
 141.208 +    }
 141.209 +    
 141.210 +    public static String stringValue(Object val) {
 141.211 +        if (val instanceof Boolean) {
 141.212 +            return ((Boolean)val ? "true" : "false");
 141.213 +        }
 141.214 +        if (isNumeric(val)) {
 141.215 +            return Long.toString(((Number)val).longValue());
 141.216 +        }
 141.217 +        if (val instanceof Float) {
 141.218 +            return Float.toString((Float)val);
 141.219 +        }
 141.220 +        if (val instanceof Double) {
 141.221 +            return Double.toString((Double)val);
 141.222 +        }
 141.223 +        return (String)val;
 141.224 +    }
 141.225 +    
 141.226 +    public static Number numberValue(Object val) {
 141.227 +        if (val instanceof String) {
 141.228 +            try {
 141.229 +                return Double.valueOf((String)val);
 141.230 +            } catch (NumberFormatException ex) {
 141.231 +                return Double.NaN;
 141.232 +            }
 141.233 +        }
 141.234 +        if (val instanceof Boolean) {
 141.235 +            return (Boolean)val ? 1 : 0;
 141.236 +        }
 141.237 +        return (Number)val;
 141.238 +    }
 141.239 +
 141.240 +    public static Character charValue(Object val) {
 141.241 +        if (val instanceof Number) {
 141.242 +            return Character.toChars(numberValue(val).intValue())[0];
 141.243 +        }
 141.244 +        if (val instanceof Boolean) {
 141.245 +            return (Boolean)val ? (char)1 : (char)0;
 141.246 +        }
 141.247 +        if (val instanceof String) {
 141.248 +            String s = (String)val;
 141.249 +            return s.isEmpty() ? (char)0 : s.charAt(0);
 141.250 +        }
 141.251 +        return (Character)val;
 141.252 +    }
 141.253 +    
 141.254 +    public static Boolean boolValue(Object val) {
 141.255 +        if (val instanceof String) {
 141.256 +            return Boolean.parseBoolean((String)val);
 141.257 +        }
 141.258 +        if (val instanceof Number) {
 141.259 +            return numberValue(val).doubleValue() != 0.0;
 141.260 +        }
 141.261 +    
 141.262 +        return Boolean.TRUE.equals(val);
 141.263 +    }
 141.264 +    
 141.265 +    public static Object find(Object object, Bindings model) {
 141.266 +        if (object == null) {
 141.267 +            return null;
 141.268 +        }
 141.269 +        if (object instanceof JSONList) {
 141.270 +            return ((JSONList<?>) object).koData();
 141.271 +        }
 141.272 +        if (object instanceof Collection) {
 141.273 +            return JSONList.koData((Collection<?>) object, model);
 141.274 +        }
 141.275 +        Proto.Type<?> type = JSON.findType(object.getClass());
 141.276 +        if (type == null) {
 141.277 +            return null;
 141.278 +        }
 141.279 +        final Proto proto = PropertyBindingAccessor.protoFor(type, object);
 141.280 +        if (proto == null) {
 141.281 +            return null;
 141.282 +        }
 141.283 +        final Bindings b = PropertyBindingAccessor.getBindings(proto, true);
 141.284 +        return b == null ? null : b.koData();
 141.285 +    }
 141.286 +
 141.287 +    public static Object find(Object object) {
 141.288 +        return find(object, null);
 141.289 +    }
 141.290 +    
 141.291 +    public static void loadJSON(
 141.292 +        BrwsrCtx c, RcvrJSON callback,
 141.293 +        String urlBefore, String urlAfter, String method,
 141.294 +        Object data
 141.295 +    ) {
 141.296 +        JSONCall call = PropertyBindingAccessor.createCall(c, callback, urlBefore, urlAfter, method, data);
 141.297 +        Transfer t = findTransfer(c);
 141.298 +        t.loadJSON(call);
 141.299 +    }
 141.300 +    public static WS openWS(
 141.301 +        BrwsrCtx c, RcvrJSON r, String url, Object data
 141.302 +    ) {
 141.303 +        WS ws = WSImpl.create(findWSTransfer(c), r);
 141.304 +        ws.send(c, url, data);
 141.305 +        return ws;
 141.306 +    }
 141.307 +    
 141.308 +    public static abstract class WS {
 141.309 +        private WS() {
 141.310 +        }
 141.311 +        
 141.312 +        public abstract void send(BrwsrCtx ctx, String url, Object model);
 141.313 +    }
 141.314 +    
 141.315 +    private static final class WSImpl<Socket> extends WS {
 141.316 +
 141.317 +        private final WSTransfer<Socket> trans;
 141.318 +        private final RcvrJSON rcvr;
 141.319 +        private Socket socket;
 141.320 +        private String prevURL;
 141.321 +
 141.322 +        private WSImpl(WSTransfer<Socket> trans, RcvrJSON rcvr) {
 141.323 +            this.trans = trans;
 141.324 +            this.rcvr = rcvr;
 141.325 +        }
 141.326 +        
 141.327 +        static <Socket> WS create(WSTransfer<Socket> t, RcvrJSON r) {
 141.328 +            return new WSImpl<Socket>(t, r);
 141.329 +        }
 141.330 +
 141.331 +        @Override
 141.332 +        public void send(BrwsrCtx ctx, String url, Object data) {
 141.333 +            Socket s = socket;
 141.334 +            if (s == null) {
 141.335 +                if (data != null) {
 141.336 +                    throw new IllegalStateException("WebSocket is not opened yet. Call with null data, was: " + data);
 141.337 +                }
 141.338 +                JSONCall call = PropertyBindingAccessor.createCall(ctx, rcvr, url, null, "WebSocket", null);
 141.339 +                socket = trans.open(url, call);
 141.340 +                prevURL = url;
 141.341 +                return;
 141.342 +            }
 141.343 +            if (data == null) {
 141.344 +                trans.close(s);
 141.345 +                socket = null;
 141.346 +                return;
 141.347 +            }
 141.348 +            if (!prevURL.equals(url)) {
 141.349 +                throw new IllegalStateException(
 141.350 +                    "Can't call to different URL " + url + " was: " + prevURL + "!"
 141.351 +                    + " Close the socket by calling it will null data first!"
 141.352 +                );
 141.353 +            }
 141.354 +            JSONCall call = PropertyBindingAccessor.createCall(ctx, rcvr, prevURL, null, "WebSocket", data);
 141.355 +            trans.send(s, call);
 141.356 +        }
 141.357 +        
 141.358 +    }
 141.359 +    
 141.360 +    private static final Map<Class,Proto.Type<?>> modelTypes;
 141.361 +    static {
 141.362 +        modelTypes = new HashMap<Class, Proto.Type<?>>();
 141.363 +    }
 141.364 +    public static void register(Class c, Proto.Type<?> type) {
 141.365 +        modelTypes.put(c, type);
 141.366 +    }
 141.367 +    
 141.368 +    public static boolean isModel(Class<?> clazz) {
 141.369 +        return findType(clazz) != null; 
 141.370 +    }
 141.371 +    
 141.372 +    static Proto.Type<?> findType(Class<?> clazz) {
 141.373 +        for (int i = 0; i < 2; i++) {
 141.374 +            Proto.Type<?> from = modelTypes.get(clazz);
 141.375 +            if (from == null) {
 141.376 +                initClass(clazz);
 141.377 +            } else {
 141.378 +                return from;
 141.379 +            }
 141.380 +        }
 141.381 +        return null;
 141.382 +    }
 141.383 +    
 141.384 +    public static <Model> Model bindTo(Model model, BrwsrCtx c) {
 141.385 +        Proto.Type<Model> from = (Proto.Type<Model>) findType(model.getClass());
 141.386 +        if (from == null) {
 141.387 +            throw new IllegalArgumentException();
 141.388 +        }
 141.389 +        return PropertyBindingAccessor.clone(from, model, c);
 141.390 +    }
 141.391 +    
 141.392 +    public static <T> T readStream(BrwsrCtx c, Class<T> modelClazz, InputStream data) 
 141.393 +    throws IOException {
 141.394 +        Transfer tr = findTransfer(c);
 141.395 +        return read(c, modelClazz, tr.toJSON((InputStream)data));
 141.396 +    }
 141.397 +    public static <T> T read(BrwsrCtx c, Class<T> modelClazz, Object data) {
 141.398 +        if (data == null) {
 141.399 +            return null;
 141.400 +        }
 141.401 +        if (modelClazz == String.class) {
 141.402 +            return modelClazz.cast(data.toString());
 141.403 +        }
 141.404 +        for (int i = 0; i < 2; i++) {
 141.405 +            Proto.Type<?> from = modelTypes.get(modelClazz);
 141.406 +            if (from == null) {
 141.407 +                initClass(modelClazz);
 141.408 +            } else {
 141.409 +                return modelClazz.cast(PropertyBindingAccessor.readFrom(from, c, data));
 141.410 +            }
 141.411 +        }
 141.412 +        throw new NullPointerException();
 141.413 +    }
 141.414 +    static void initClass(Class<?> modelClazz) {
 141.415 +        try {
 141.416 +            // try to resolve the class
 141.417 +            ClassLoader l;
 141.418 +            try {
 141.419 +                l = modelClazz.getClassLoader();
 141.420 +            } catch (SecurityException ex) {
 141.421 +                l = null;
 141.422 +            }
 141.423 +            if (l != null) {
 141.424 +                Class.forName(modelClazz.getName(), true, l);
 141.425 +            }
 141.426 +            modelClazz.newInstance();
 141.427 +        } catch (Exception ex) {
 141.428 +            // ignore and try again
 141.429 +        }
 141.430 +    }
 141.431 +    
 141.432 +    private static final class EmptyTech
 141.433 +    implements Technology<Object>, Transfer, WSTransfer<Void> {
 141.434 +        private static final EmptyTech EMPTY = new EmptyTech();
 141.435 +
 141.436 +        @Override
 141.437 +        public Object wrapModel(Object model) {
 141.438 +            return model;
 141.439 +        }
 141.440 +
 141.441 +        @Override
 141.442 +        public void valueHasMutated(Object data, String propertyName) {
 141.443 +        }
 141.444 +
 141.445 +        @Override
 141.446 +        public void bind(PropertyBinding b, Object model, Object data) {
 141.447 +        }
 141.448 +
 141.449 +        @Override
 141.450 +        public void expose(FunctionBinding fb, Object model, Object d) {
 141.451 +        }
 141.452 +
 141.453 +        @Override
 141.454 +        public void applyBindings(Object data) {
 141.455 +        }
 141.456 +
 141.457 +        @Override
 141.458 +        public Object wrapArray(Object[] arr) {
 141.459 +            return arr;
 141.460 +        }
 141.461 +
 141.462 +        @Override
 141.463 +        public void extract(Object obj, String[] props, Object[] values) {
 141.464 +            for (int i = 0; i < values.length; i++) {
 141.465 +                values[i] = null;
 141.466 +            }
 141.467 +        }
 141.468 +
 141.469 +        @Override
 141.470 +        public void loadJSON(JSONCall call) {
 141.471 +            call.notifyError(new UnsupportedOperationException());
 141.472 +        }
 141.473 +
 141.474 +        @Override
 141.475 +        public <M> M toModel(Class<M> modelClass, Object data) {
 141.476 +            return modelClass.cast(data);
 141.477 +        }
 141.478 +
 141.479 +        @Override
 141.480 +        public Object toJSON(InputStream is) throws IOException {
 141.481 +            throw new IOException("Not supported");
 141.482 +        }
 141.483 +
 141.484 +        @Override
 141.485 +        public synchronized void runSafe(Runnable r) {
 141.486 +            r.run();
 141.487 +        }
 141.488 +
 141.489 +        @Override
 141.490 +        public Void open(String url, JSONCall onReply) {
 141.491 +            onReply.notifyError(new UnsupportedOperationException("WebSockets not supported!"));
 141.492 +            return null;
 141.493 +        }
 141.494 +
 141.495 +        @Override
 141.496 +        public void send(Void socket, JSONCall data) {
 141.497 +        }
 141.498 +
 141.499 +        @Override
 141.500 +        public void close(Void socket) {
 141.501 +        }
 141.502 +    }
 141.503 +    
 141.504 +}
   142.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   142.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/JSONList.java	Tue Jan 07 08:21:57 2014 +0100
   142.3 @@ -0,0 +1,208 @@
   142.4 +/**
   142.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   142.6 + *
   142.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   142.8 + *
   142.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  142.10 + * Other names may be trademarks of their respective owners.
  142.11 + *
  142.12 + * The contents of this file are subject to the terms of either the GNU
  142.13 + * General Public License Version 2 only ("GPL") or the Common
  142.14 + * Development and Distribution License("CDDL") (collectively, the
  142.15 + * "License"). You may not use this file except in compliance with the
  142.16 + * License. You can obtain a copy of the License at
  142.17 + * http://www.netbeans.org/cddl-gplv2.html
  142.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  142.19 + * specific language governing permissions and limitations under the
  142.20 + * License.  When distributing the software, include this License Header
  142.21 + * Notice in each file and include the License file at
  142.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  142.23 + * particular file as subject to the "Classpath" exception as provided
  142.24 + * by Oracle in the GPL Version 2 section of the License file that
  142.25 + * accompanied this code. If applicable, add the following below the
  142.26 + * License Header, with the fields enclosed by brackets [] replaced by
  142.27 + * your own identifying information:
  142.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  142.29 + *
  142.30 + * Contributor(s):
  142.31 + *
  142.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  142.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  142.34 + *
  142.35 + * If you wish your version of this file to be governed by only the CDDL
  142.36 + * or only the GPL Version 2, indicate your decision by adding
  142.37 + * "[Contributor] elects to include this software in this distribution
  142.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  142.39 + * single choice of license, a recipient has the option to distribute
  142.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  142.41 + * to extend the choice of license to its licensees as provided above.
  142.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  142.43 + * Version 2 license, then the option applies only if the new code is
  142.44 + * made subject to such option by the copyright holder.
  142.45 + */
  142.46 +package org.netbeans.html.json.impl;
  142.47 +
  142.48 +import java.lang.reflect.Array;
  142.49 +import java.util.ArrayList;
  142.50 +import java.util.Collection;
  142.51 +import java.util.Iterator;
  142.52 +import org.apidesign.html.json.spi.Proto;
  142.53 +
  142.54 +/**
  142.55 + *
  142.56 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  142.57 + */
  142.58 +public final class JSONList<T> extends ArrayList<T> {
  142.59 +    private final Proto proto;
  142.60 +    private final String name;
  142.61 +    private final String[] deps;
  142.62 +    private final int index;
  142.63 +
  142.64 +    public JSONList(Proto proto, String name, int changeIndex, String... deps) {
  142.65 +        this.proto = proto;
  142.66 +        this.name = name;
  142.67 +        this.deps = deps;
  142.68 +        this.index = changeIndex;
  142.69 +    }
  142.70 +    
  142.71 +    public void init(Object values) {
  142.72 +        int len;
  142.73 +        if (values == null || (len = Array.getLength(values)) == 0) {
  142.74 +            return;
  142.75 +        }
  142.76 +        for (int i = 0; i < len; i++) {
  142.77 +            Object data = Array.get(values, i);
  142.78 +            super.add((T)data);
  142.79 +        }
  142.80 +    }
  142.81 +    public static <T> void init(Collection<T> to, Object values) {
  142.82 +        int len;
  142.83 +        if (values == null || (len = Array.getLength(values)) == 0) {
  142.84 +            return;
  142.85 +        }
  142.86 +        for (int i = 0; i < len; i++) {
  142.87 +            Object data = Array.get(values, i);
  142.88 +            to.add((T)data);
  142.89 +        }
  142.90 +    }
  142.91 +    
  142.92 +    @Override
  142.93 +    public boolean add(T e) {
  142.94 +        boolean ret = super.add(e);
  142.95 +        notifyChange();
  142.96 +        return ret;
  142.97 +    }
  142.98 +
  142.99 +    @Override
 142.100 +    public boolean addAll(Collection<? extends T> c) {
 142.101 +        boolean ret = super.addAll(c);
 142.102 +        notifyChange();
 142.103 +        return ret;
 142.104 +    }
 142.105 +
 142.106 +    @Override
 142.107 +    public boolean addAll(int index, Collection<? extends T> c) {
 142.108 +        boolean ret = super.addAll(index, c);
 142.109 +        notifyChange();
 142.110 +        return ret;
 142.111 +    }
 142.112 +
 142.113 +    @Override
 142.114 +    public boolean remove(Object o) {
 142.115 +        boolean ret = super.remove(o);
 142.116 +        notifyChange();
 142.117 +        return ret;
 142.118 +    }
 142.119 +
 142.120 +    @Override
 142.121 +    public void clear() {
 142.122 +        super.clear();
 142.123 +        notifyChange();
 142.124 +    }
 142.125 +
 142.126 +    @Override
 142.127 +    public boolean removeAll(Collection<?> c) {
 142.128 +        boolean ret = super.removeAll(c);
 142.129 +        notifyChange();
 142.130 +        return ret;
 142.131 +    }
 142.132 +
 142.133 +    @Override
 142.134 +    public boolean retainAll(Collection<?> c) {
 142.135 +        boolean ret = super.retainAll(c);
 142.136 +        notifyChange();
 142.137 +        return ret;
 142.138 +    }
 142.139 +
 142.140 +    @Override
 142.141 +    public T set(int index, T element) {
 142.142 +        T ret = super.set(index, element);
 142.143 +        notifyChange();
 142.144 +        return ret;
 142.145 +    }
 142.146 +
 142.147 +    @Override
 142.148 +    public void add(int index, T element) {
 142.149 +        super.add(index, element);
 142.150 +        notifyChange();
 142.151 +    }
 142.152 +
 142.153 +    @Override
 142.154 +    public T remove(int index) {
 142.155 +        T ret = super.remove(index);
 142.156 +        notifyChange();
 142.157 +        return ret;
 142.158 +    }
 142.159 +
 142.160 +    @Override
 142.161 +    public String toString() {
 142.162 +        Iterator<T> it = iterator();
 142.163 +        if (!it.hasNext()) {
 142.164 +            return "[]";
 142.165 +        }
 142.166 +        String sep = "";
 142.167 +        StringBuilder sb = new StringBuilder();
 142.168 +        sb.append('[');
 142.169 +        while (it.hasNext()) {
 142.170 +            T t = it.next();
 142.171 +            sb.append(sep);
 142.172 +            sb.append(JSON.toJSON(t));
 142.173 +            sep = ",";
 142.174 +        }
 142.175 +        sb.append(']');
 142.176 +        return sb.toString();
 142.177 +    }
 142.178 +
 142.179 +    private void notifyChange() {
 142.180 +        Bindings m = PropertyBindingAccessor.getBindings(proto, false);
 142.181 +        if (m != null) {
 142.182 +            m.valueHasMutated(name);
 142.183 +            for (String dependant : deps) {
 142.184 +                m.valueHasMutated(dependant);
 142.185 +            }
 142.186 +            if (index >= 0) {
 142.187 +                PropertyBindingAccessor.notifyProtoChange(proto, index);
 142.188 +            }
 142.189 +        }
 142.190 +    }
 142.191 +
 142.192 +    @Override
 142.193 +    public JSONList clone() {
 142.194 +        throw new UnsupportedOperationException();
 142.195 +    }
 142.196 +
 142.197 +    static final Object koData(Collection<?> c, Bindings m) {
 142.198 +        Object[] arr = c.toArray(new Object[c.size()]);
 142.199 +        for (int i = 0; i < arr.length; i++) {
 142.200 +            Object r = JSON.find(arr[i], m);
 142.201 +            if (r != null) {
 142.202 +                arr[i] = r;
 142.203 +            }
 142.204 +        }
 142.205 +        return m.wrapArray(arr);
 142.206 +    }
 142.207 +
 142.208 +    final Object koData() {
 142.209 +        return koData(this, PropertyBindingAccessor.getBindings(proto, true));
 142.210 +    }
 142.211 +}
   143.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   143.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/ModelProcessor.java	Tue Jan 07 08:21:57 2014 +0100
   143.3 @@ -0,0 +1,1778 @@
   143.4 +/**
   143.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   143.6 + *
   143.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   143.8 + *
   143.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  143.10 + * Other names may be trademarks of their respective owners.
  143.11 + *
  143.12 + * The contents of this file are subject to the terms of either the GNU
  143.13 + * General Public License Version 2 only ("GPL") or the Common
  143.14 + * Development and Distribution License("CDDL") (collectively, the
  143.15 + * "License"). You may not use this file except in compliance with the
  143.16 + * License. You can obtain a copy of the License at
  143.17 + * http://www.netbeans.org/cddl-gplv2.html
  143.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  143.19 + * specific language governing permissions and limitations under the
  143.20 + * License.  When distributing the software, include this License Header
  143.21 + * Notice in each file and include the License file at
  143.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  143.23 + * particular file as subject to the "Classpath" exception as provided
  143.24 + * by Oracle in the GPL Version 2 section of the License file that
  143.25 + * accompanied this code. If applicable, add the following below the
  143.26 + * License Header, with the fields enclosed by brackets [] replaced by
  143.27 + * your own identifying information:
  143.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  143.29 + *
  143.30 + * Contributor(s):
  143.31 + *
  143.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  143.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  143.34 + *
  143.35 + * If you wish your version of this file to be governed by only the CDDL
  143.36 + * or only the GPL Version 2, indicate your decision by adding
  143.37 + * "[Contributor] elects to include this software in this distribution
  143.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  143.39 + * single choice of license, a recipient has the option to distribute
  143.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  143.41 + * to extend the choice of license to its licensees as provided above.
  143.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  143.43 + * Version 2 license, then the option applies only if the new code is
  143.44 + * made subject to such option by the copyright holder.
  143.45 + */
  143.46 +package org.netbeans.html.json.impl;
  143.47 +
  143.48 +import java.io.IOException;
  143.49 +import java.io.OutputStreamWriter;
  143.50 +import java.io.StringWriter;
  143.51 +import java.io.Writer;
  143.52 +import java.lang.annotation.AnnotationTypeMismatchException;
  143.53 +import java.lang.annotation.IncompleteAnnotationException;
  143.54 +import java.lang.reflect.Method;
  143.55 +import java.util.ArrayList;
  143.56 +import java.util.Arrays;
  143.57 +import java.util.Collection;
  143.58 +import java.util.Collections;
  143.59 +import java.util.HashMap;
  143.60 +import java.util.HashSet;
  143.61 +import java.util.LinkedHashSet;
  143.62 +import java.util.List;
  143.63 +import java.util.Map;
  143.64 +import java.util.ResourceBundle;
  143.65 +import java.util.Set;
  143.66 +import java.util.WeakHashMap;
  143.67 +import java.util.logging.Level;
  143.68 +import java.util.logging.Logger;
  143.69 +import javax.annotation.processing.AbstractProcessor;
  143.70 +import javax.annotation.processing.Completion;
  143.71 +import javax.annotation.processing.Completions;
  143.72 +import javax.annotation.processing.ProcessingEnvironment;
  143.73 +import javax.annotation.processing.Processor;
  143.74 +import javax.annotation.processing.RoundEnvironment;
  143.75 +import javax.annotation.processing.SupportedAnnotationTypes;
  143.76 +import javax.annotation.processing.SupportedSourceVersion;
  143.77 +import javax.lang.model.SourceVersion;
  143.78 +import javax.lang.model.element.AnnotationMirror;
  143.79 +import javax.lang.model.element.AnnotationValue;
  143.80 +import javax.lang.model.element.Element;
  143.81 +import javax.lang.model.element.ElementKind;
  143.82 +import javax.lang.model.element.ExecutableElement;
  143.83 +import javax.lang.model.element.Modifier;
  143.84 +import javax.lang.model.element.PackageElement;
  143.85 +import javax.lang.model.element.TypeElement;
  143.86 +import javax.lang.model.element.VariableElement;
  143.87 +import javax.lang.model.type.ArrayType;
  143.88 +import javax.lang.model.type.DeclaredType;
  143.89 +import javax.lang.model.type.MirroredTypeException;
  143.90 +import javax.lang.model.type.TypeKind;
  143.91 +import javax.lang.model.type.TypeMirror;
  143.92 +import javax.lang.model.util.Elements;
  143.93 +import javax.lang.model.util.Types;
  143.94 +import javax.tools.Diagnostic;
  143.95 +import javax.tools.FileObject;
  143.96 +import net.java.html.json.ComputedProperty;
  143.97 +import net.java.html.json.Model;
  143.98 +import net.java.html.json.Function;
  143.99 +import net.java.html.json.ModelOperation;
 143.100 +import net.java.html.json.OnPropertyChange;
 143.101 +import net.java.html.json.OnReceive;
 143.102 +import net.java.html.json.Property;
 143.103 +import org.openide.util.lookup.ServiceProvider;
 143.104 +
 143.105 +/** Annotation processor to process {@link Model @Model} annotations and
 143.106 + * generate appropriate model classes.
 143.107 + *
 143.108 + * @author Jaroslav Tulach <jtulach@netbeans.org>
 143.109 + */
 143.110 +@ServiceProvider(service=Processor.class)
 143.111 +@SupportedSourceVersion(SourceVersion.RELEASE_6)
 143.112 +@SupportedAnnotationTypes({
 143.113 +    "net.java.html.json.Model",
 143.114 +    "net.java.html.json.ModelOperation",
 143.115 +    "net.java.html.json.Function",
 143.116 +    "net.java.html.json.OnReceive",
 143.117 +    "net.java.html.json.OnPropertyChange",
 143.118 +    "net.java.html.json.ComputedProperty",
 143.119 +    "net.java.html.json.Property"
 143.120 +})
 143.121 +public final class ModelProcessor extends AbstractProcessor {
 143.122 +    private static final Logger LOG = Logger.getLogger(ModelProcessor.class.getName());
 143.123 +    private final Map<Element,String> models = new WeakHashMap<Element,String>();
 143.124 +    private final Map<Element,Prprt[]> verify = new WeakHashMap<Element,Prprt[]>();
 143.125 +    @Override
 143.126 +    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
 143.127 +        boolean ok = true;
 143.128 +        for (Element e : roundEnv.getElementsAnnotatedWith(Model.class)) {
 143.129 +            if (!processModel(e)) {
 143.130 +                ok = false;
 143.131 +            }
 143.132 +        }
 143.133 +        if (roundEnv.processingOver()) {
 143.134 +            models.clear();
 143.135 +            for (Map.Entry<Element, Prprt[]> entry : verify.entrySet()) {
 143.136 +                TypeElement te = (TypeElement)entry.getKey();
 143.137 +                String fqn = processingEnv.getElementUtils().getBinaryName(te).toString();
 143.138 +                Element finalElem = processingEnv.getElementUtils().getTypeElement(fqn);
 143.139 +                if (finalElem == null) {
 143.140 +                    continue;
 143.141 +                }
 143.142 +                Prprt[] props;
 143.143 +                Model m = finalElem.getAnnotation(Model.class);
 143.144 +                if (m == null) {
 143.145 +                    continue;
 143.146 +                }
 143.147 +                props = Prprt.wrap(processingEnv, finalElem, m.properties());
 143.148 +                for (Prprt p : props) {
 143.149 +                    boolean[] isModel = { false };
 143.150 +                    boolean[] isEnum = { false };
 143.151 +                    boolean[] isPrimitive = { false };
 143.152 +                    String t = checkType(p, isModel, isEnum, isPrimitive);
 143.153 +                    if (isEnum[0]) {
 143.154 +                        continue;
 143.155 +                    }
 143.156 +                    if (isPrimitive[0]) {
 143.157 +                        continue;
 143.158 +                    }
 143.159 +                    if (isModel[0]) {
 143.160 +                        continue;
 143.161 +                    }
 143.162 +                    if ("java.lang.String".equals(t)) {
 143.163 +                        continue;
 143.164 +                    }
 143.165 +                    error("The type " + t + " should be defined by @Model annotation", entry.getKey());
 143.166 +                }
 143.167 +            }
 143.168 +            verify.clear();
 143.169 +        }
 143.170 +        return ok;
 143.171 +    }
 143.172 +
 143.173 +    private void error(String msg, Element e) {
 143.174 +        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e);
 143.175 +    }
 143.176 +    
 143.177 +    private boolean processModel(Element e) {
 143.178 +        boolean ok = true;
 143.179 +        Model m = e.getAnnotation(Model.class);
 143.180 +        if (m == null) {
 143.181 +            return true;
 143.182 +        }
 143.183 +        String pkg = findPkgName(e);
 143.184 +        Writer w;
 143.185 +        String className = m.className();
 143.186 +        models.put(e, className);
 143.187 +        try {
 143.188 +            StringWriter body = new StringWriter();
 143.189 +            StringBuilder onReceiveType = new StringBuilder();
 143.190 +            List<String> propsGetSet = new ArrayList<String>();
 143.191 +            List<String> functions = new ArrayList<String>();
 143.192 +            Map<String, Collection<String>> propsDeps = new HashMap<String, Collection<String>>();
 143.193 +            Map<String, Collection<String>> functionDeps = new HashMap<String, Collection<String>>();
 143.194 +            Prprt[] props = createProps(e, m.properties());
 143.195 +            
 143.196 +            if (!generateComputedProperties(body, props, e.getEnclosedElements(), propsGetSet, propsDeps)) {
 143.197 +                ok = false;
 143.198 +            }
 143.199 +            if (!generateOnChange(e, propsDeps, props, className, functionDeps)) {
 143.200 +                ok = false;
 143.201 +            }
 143.202 +            if (!generateProperties(e, body, className, props, propsGetSet, propsDeps, functionDeps)) {
 143.203 +                ok = false;
 143.204 +            }
 143.205 +            if (!generateFunctions(e, body, className, e.getEnclosedElements(), functions)) {
 143.206 +                ok = false;
 143.207 +            }
 143.208 +            if (!generateReceive(e, body, className, e.getEnclosedElements(), onReceiveType)) {
 143.209 +                ok = false;
 143.210 +            }
 143.211 +            if (!generateOperation(e, body, className, e.getEnclosedElements())) {
 143.212 +                ok = false;
 143.213 +            }
 143.214 +            FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
 143.215 +            w = new OutputStreamWriter(java.openOutputStream());
 143.216 +            try {
 143.217 +                w.append("package " + pkg + ";\n");
 143.218 +                w.append("import net.java.html.json.*;\n");
 143.219 +                w.append("public final class ").append(className).append(" implements Cloneable {\n");
 143.220 +                w.append("  private static final Html4JavaType TYPE = new Html4JavaType();\n");
 143.221 +                w.append("  private final org.apidesign.html.json.spi.Proto proto;\n");
 143.222 +                w.append(body.toString());
 143.223 +                w.append("  private static Class<" + inPckName(e) + "> modelFor() { return null; }\n");
 143.224 +                w.append("  private ").append(className).append("(net.java.html.BrwsrCtx context) {\n");
 143.225 +                w.append("    this.proto = TYPE.createProto(this, context);\n");
 143.226 +                for (Prprt p : props) {
 143.227 +                    if (p.array()) {
 143.228 +                        final String tn = typeName(e, p);
 143.229 +                        String[] gs = toGetSet(p.name(), tn, p.array());
 143.230 +                        w.write("    this.prop_" + p.name() + " = proto.createList(\""
 143.231 +                            + p.name() + "\"");
 143.232 +                        if (functionDeps.containsKey(p.name())) {
 143.233 +                            int index = Arrays.asList(functionDeps.keySet().toArray()).indexOf(p.name());
 143.234 +                            w.write(", " + index);
 143.235 +                        } else {
 143.236 +                            w.write(", -1");
 143.237 +                        }
 143.238 +                        Collection<String> dependants = propsDeps.get(p.name());
 143.239 +                        if (dependants != null) {
 143.240 +                            for (String depProp : dependants) {
 143.241 +                                w.write(", ");
 143.242 +                                w.write('\"');
 143.243 +                                w.write(depProp);
 143.244 +                                w.write('\"');
 143.245 +                            }
 143.246 +                        }
 143.247 +                        w.write(")");
 143.248 +                        w.write(";\n");
 143.249 +                    }
 143.250 +                }
 143.251 +                w.append("  };\n");
 143.252 +                w.append("  public ").append(className).append("() {\n");
 143.253 +                w.append("    this(net.java.html.BrwsrCtx.findDefault(").append(className).append(".class));\n");
 143.254 +                for (Prprt p : props) {
 143.255 +                    if (!p.array()) {
 143.256 +                        boolean[] isModel = {false};
 143.257 +                        boolean[] isEnum = {false};
 143.258 +                        boolean isPrimitive[] = {false};
 143.259 +                        String tn = checkType(p, isModel, isEnum, isPrimitive);
 143.260 +                        if (isModel[0]) {
 143.261 +                            w.write("    prop_" + p.name() + " = new " + tn + "();\n");
 143.262 +                        }
 143.263 +                    }
 143.264 +                }
 143.265 +                w.append("  };\n");
 143.266 +                if (props.length > 0) {
 143.267 +                    w.append("  public ").append(className).append("(");
 143.268 +                    Prprt firstArray = null;
 143.269 +                    String sep = "";
 143.270 +                    for (Prprt p : props) {
 143.271 +                        if (p.array()) {
 143.272 +                            if (firstArray == null) {
 143.273 +                                firstArray = p;
 143.274 +                            }
 143.275 +                            continue;
 143.276 +                        }
 143.277 +                        String tn = typeName(e, p);
 143.278 +                        w.write(sep);
 143.279 +                        w.write(tn);
 143.280 +                        w.write(" " + p.name());
 143.281 +                        sep = ", ";
 143.282 +                    }
 143.283 +                    if (firstArray != null) {
 143.284 +                        String tn;
 143.285 +                        boolean[] isModel = {false};
 143.286 +                        boolean[] isEnum = {false};
 143.287 +                        boolean isPrimitive[] = {false};
 143.288 +                        tn = checkType(firstArray, isModel, isEnum, isPrimitive);
 143.289 +                        w.write(sep);
 143.290 +                        w.write(tn);
 143.291 +                        w.write("... " + firstArray.name());
 143.292 +                    }
 143.293 +                    w.append(") {\n");
 143.294 +                    w.append("    this(net.java.html.BrwsrCtx.findDefault(").append(className).append(".class));\n");
 143.295 +                    for (Prprt p : props) {
 143.296 +                        if (p.array()) {
 143.297 +                            continue;
 143.298 +                        }
 143.299 +                        w.write("    this.prop_" + p.name() + " = " + p.name() + ";\n");
 143.300 +                    }
 143.301 +                    if (firstArray != null) {
 143.302 +                        w.write("    proto.initTo(this.prop_" + firstArray.name() + ", " + firstArray.name() + ");\n");
 143.303 +                    }
 143.304 +                    w.append("  };\n");
 143.305 +                }
 143.306 +                w.append("  private static class Html4JavaType extends org.apidesign.html.json.spi.Proto.Type<").append(className).append("> {\n");
 143.307 +                w.append("    private Html4JavaType() {\n      super(").append(className).append(".class, ").
 143.308 +                    append(inPckName(e)).append(".class, " + (propsGetSet.size() / 5) + ", "
 143.309 +                    + (functions.size() / 2) + ");\n");
 143.310 +                {
 143.311 +                    for (int i = 0; i < propsGetSet.size(); i += 5) {
 143.312 +                        w.append("      registerProperty(\"").append(propsGetSet.get(i)).append("\", ");
 143.313 +                        w.append((i / 5) + ", " + (propsGetSet.get(i + 2) == null) + ");\n");
 143.314 +                    }
 143.315 +                }
 143.316 +                {
 143.317 +                    for (int i = 0; i < functions.size(); i += 2) {
 143.318 +                        w.append("      registerFunction(\"").append(functions.get(i)).append("\", ");
 143.319 +                        w.append((i / 2) + ");\n");
 143.320 +                    }
 143.321 +                }
 143.322 +                w.append("    }\n");
 143.323 +                w.append("    @Override public void setValue(" + className + " data, int type, Object value) {\n");
 143.324 +                w.append("      switch (type) {\n");
 143.325 +                for (int i = 0; i < propsGetSet.size(); i += 5) {
 143.326 +                    final String set = propsGetSet.get(i + 2);
 143.327 +                    String tn = propsGetSet.get(i + 4);
 143.328 +                    String btn = findBoxedType(tn);
 143.329 +                    if (btn != null) {
 143.330 +                        tn = btn;
 143.331 +                    }
 143.332 +                    if (set != null) {
 143.333 +                        w.append("        case " + (i / 5) + ": data." + strip(set) + "(TYPE.extractValue(" + tn + ".class, value)); return;\n");
 143.334 +                    }
 143.335 +                }
 143.336 +                w.append("      }\n");
 143.337 +                w.append("    }\n");
 143.338 +                w.append("    @Override public Object getValue(" + className + " data, int type) {\n");
 143.339 +                w.append("      switch (type) {\n");
 143.340 +                for (int i = 0; i < propsGetSet.size(); i += 5) {
 143.341 +                    final String get = propsGetSet.get(i + 1);
 143.342 +                    if (get != null) {
 143.343 +                        w.append("        case " + (i / 5) + ": return data." + strip(get) + "();\n");
 143.344 +                    }
 143.345 +                }
 143.346 +                w.append("      }\n");
 143.347 +                w.append("      throw new UnsupportedOperationException();\n");
 143.348 +                w.append("    }\n");
 143.349 +                w.append("    @Override public void call(" + className + " model, int type, Object data, Object ev) {\n");
 143.350 +                w.append("      switch (type) {\n");
 143.351 +                for (int i = 0; i < functions.size(); i += 2) {
 143.352 +                    final String name = functions.get(i);
 143.353 +                    w.append("        case " + (i / 2) + ": model." + name + "(data, ev); return;\n");
 143.354 +                }
 143.355 +                w.append("      }\n");
 143.356 +                w.append("      throw new UnsupportedOperationException();\n");
 143.357 +                w.append("    }\n");
 143.358 +                w.append("    @Override public org.apidesign.html.json.spi.Proto protoFor(Object obj) {\n");
 143.359 +                w.append("      return ((" + className + ")obj).proto;");
 143.360 +                w.append("    }\n");
 143.361 +                w.append("    @Override public void onChange(" + className + " model, int type) {\n");
 143.362 +                w.append("      switch (type) {\n");
 143.363 +                {
 143.364 +                    String[] arr = functionDeps.keySet().toArray(new String[0]);
 143.365 +                    for (int i = 0; i < arr.length; i++) {
 143.366 +                        Collection<String> onChange = functionDeps.get(arr[i]);
 143.367 +                        if (onChange != null) {
 143.368 +                            w.append("      case " + i + ":\n");
 143.369 +                            for (String call : onChange) {
 143.370 +                                w.append("      ").append(call).append("\n");
 143.371 +                            }
 143.372 +                            w.write("      return;\n");
 143.373 +                        }
 143.374 +                    }
 143.375 +                }
 143.376 +                w.append("    }\n");
 143.377 +                w.append("      throw new UnsupportedOperationException();\n");
 143.378 +                w.append("    }\n");
 143.379 +                w.append(onReceiveType);
 143.380 +                w.append("    @Override public " + className + " read(net.java.html.BrwsrCtx c, Object json) { return new " + className + "(c, json); }\n");
 143.381 +                w.append("    @Override public " + className + " cloneTo(" + className + " o, net.java.html.BrwsrCtx c) { return o.clone(c); }\n");
 143.382 +                w.append("  }\n");
 143.383 +                w.append("  private ").append(className).append("(net.java.html.BrwsrCtx c, Object json) {\n");
 143.384 +                w.append("    this(c);\n");
 143.385 +                int values = 0;
 143.386 +                for (int i = 0; i < propsGetSet.size(); i += 5) {
 143.387 +                    Prprt p = findPrprt(props, propsGetSet.get(i));
 143.388 +                    if (p == null) {
 143.389 +                        continue;
 143.390 +                    }
 143.391 +                    values++;
 143.392 +                }
 143.393 +                w.append("    Object[] ret = new Object[" + values + "];\n");
 143.394 +                w.append("    proto.extract(json, new String[] {\n");
 143.395 +                for (int i = 0; i < propsGetSet.size(); i += 5) {
 143.396 +                    Prprt p = findPrprt(props, propsGetSet.get(i));
 143.397 +                    if (p == null) {
 143.398 +                        continue;
 143.399 +                    }
 143.400 +                    w.append("      \"").append(propsGetSet.get(i)).append("\",\n");
 143.401 +                }
 143.402 +                w.append("    }, ret);\n");
 143.403 +                for (int i = 0, cnt = 0, prop = 0; i < propsGetSet.size(); i += 5) {
 143.404 +                    final String pn = propsGetSet.get(i);
 143.405 +                    Prprt p = findPrprt(props, pn);
 143.406 +                    if (p == null) {
 143.407 +                        continue;
 143.408 +                    }
 143.409 +                    boolean[] isModel = { false };
 143.410 +                    boolean[] isEnum = { false };
 143.411 +                    boolean isPrimitive[] = { false };
 143.412 +                    String type = checkType(props[prop++], isModel, isEnum, isPrimitive);
 143.413 +                    if (p.array()) {
 143.414 +                        w.append("    if (ret[" + cnt + "] instanceof Object[]) {\n");
 143.415 +                        w.append("      for (Object e : ((Object[])ret[" + cnt + "])) {\n");
 143.416 +                        if (isModel[0]) {
 143.417 +                            w.append("        this.prop_").append(pn).append(".add(proto.read");
 143.418 +                            w.append("(" + type + ".class, e));\n");
 143.419 +                        } else if (isEnum[0]) {
 143.420 +                            w.append("        this.prop_").append(pn);
 143.421 +                            w.append(".add(e == null ? null : ");
 143.422 +                            w.append(type).append(".valueOf(TYPE.stringValue(e)));\n");
 143.423 +                        } else {
 143.424 +                            if (isPrimitive(type)) {
 143.425 +                                w.append("        this.prop_").append(pn).append(".add(TYPE.numberValue(e).");
 143.426 +                                w.append(type).append("Value());\n");
 143.427 +                            } else {
 143.428 +                                w.append("        this.prop_").append(pn).append(".add((");
 143.429 +                                w.append(type).append(")e);\n");
 143.430 +                            }
 143.431 +                        }
 143.432 +                        w.append("      }\n");
 143.433 +                        w.append("    }\n");
 143.434 +                    } else {
 143.435 +                        if (isEnum[0]) {
 143.436 +                            w.append("    try {\n");
 143.437 +                            w.append("    this.prop_").append(pn);
 143.438 +                            w.append(" = ret[" + cnt + "] == null ? null : ");
 143.439 +                            w.append(type).append(".valueOf(TYPE.stringValue(ret[" + cnt + "]));\n");
 143.440 +                            w.append("    } catch (IllegalArgumentException ex) {\n");
 143.441 +                            w.append("      ex.printStackTrace();\n");
 143.442 +                            w.append("    }\n");
 143.443 +                        } else if (isPrimitive(type)) {
 143.444 +                            w.append("    this.prop_").append(pn);
 143.445 +                            w.append(" = ret[" + cnt + "] == null ? ");
 143.446 +                            if ("char".equals(type)) {
 143.447 +                                w.append("0 : (TYPE.charValue(");
 143.448 +                            } else if ("boolean".equals(type)) {
 143.449 +                                w.append("false : (TYPE.boolValue(");
 143.450 +                            } else {
 143.451 +                                w.append("0 : (TYPE.numberValue(");
 143.452 +                            }
 143.453 +                            w.append("ret[" + cnt + "])).");
 143.454 +                            w.append(type).append("Value();\n");
 143.455 +                        } else if (isModel[0]) {
 143.456 +                            w.append("    this.prop_").append(pn).append(" = proto.read");
 143.457 +                            w.append("(" + type + ".class, ");
 143.458 +                            w.append("ret[" + cnt + "]);\n");
 143.459 +                        }else {
 143.460 +                            w.append("    this.prop_").append(pn);
 143.461 +                            w.append(" = (").append(type).append(')');
 143.462 +                            w.append("ret[" + cnt + "];\n");
 143.463 +                        }
 143.464 +                    }
 143.465 +                    cnt++;
 143.466 +                }
 143.467 +                w.append("  }\n");
 143.468 +                writeToString(props, w);
 143.469 +                writeClone(className, props, w);
 143.470 +                w.write("  /** Activates this model instance in the current {@link \n"
 143.471 +                    + "net.java.html.json.Models#bind(java.lang.Object, net.java.html.BrwsrCtx) browser context}. \n"
 143.472 +                    + "In case of using Knockout technology, this means to \n"
 143.473 +                    + "bind JSON like data in this model instance with Knockout tags in \n"
 143.474 +                    + "the surrounding HTML page.\n"
 143.475 +                    + "*/\n"
 143.476 +                );
 143.477 +                w.write("  public " + className + " applyBindings() {\n");
 143.478 +                w.write("    proto.applyBindings();\n");
 143.479 +                w.write("    return this;\n");
 143.480 +                w.write("  }\n");
 143.481 +                w.write("  public boolean equals(Object o) {\n");
 143.482 +                w.write("    if (o == this) return true;\n");
 143.483 +                w.write("    if (!(o instanceof " + className + ")) return false;\n");
 143.484 +                w.write("    " + className + " p = (" + className + ")o;\n");
 143.485 +                for (Prprt p : props) {
 143.486 +                    w.write("    if (!TYPE.isSame(prop_" + p.name() + ", p.prop_" + p.name() + ")) return false;\n");
 143.487 +                }
 143.488 +                w.write("    return true;\n");
 143.489 +                w.write("  }\n");
 143.490 +                w.write("  public int hashCode() {\n");
 143.491 +                w.write("    int h = " + className + ".class.getName().hashCode();\n");
 143.492 +                for (Prprt p : props) {
 143.493 +                    w.write("    h = TYPE.hashPlus(prop_" + p.name() + ", h);\n");
 143.494 +                }
 143.495 +                w.write("    return h;\n");
 143.496 +                w.write("  }\n");
 143.497 +                w.write("}\n");
 143.498 +            } finally {
 143.499 +                w.close();
 143.500 +            }
 143.501 +        } catch (IOException ex) {
 143.502 +            error("Can't create " + className + ".java", e);
 143.503 +            return false;
 143.504 +        }
 143.505 +        return ok;
 143.506 +    }
 143.507 +    
 143.508 +    private boolean generateProperties(
 143.509 +        Element where,
 143.510 +        Writer w, String className, Prprt[] properties,
 143.511 +        Collection<String> props, 
 143.512 +        Map<String,Collection<String>> deps,
 143.513 +        Map<String,Collection<String>> functionDeps
 143.514 +    ) throws IOException {
 143.515 +        boolean ok = true;
 143.516 +        for (Prprt p : properties) {
 143.517 +            final String tn;
 143.518 +            tn = typeName(where, p);
 143.519 +            String[] gs = toGetSet(p.name(), tn, p.array());
 143.520 +            String castTo;
 143.521 +            
 143.522 +            if (p.array()) {
 143.523 +                w.write("  private final java.util.List<" + tn + "> prop_" + p.name() + ";\n");
 143.524 +            
 143.525 +                castTo = "java.util.List";
 143.526 +                w.write("  public java.util.List<" + tn + "> " + gs[0] + "() {\n");
 143.527 +                w.write("    proto.verifyUnlocked();\n");
 143.528 +                w.write("    return prop_" + p.name() + ";\n");
 143.529 +                w.write("  }\n");
 143.530 +            } else {
 143.531 +                castTo = tn;
 143.532 +                w.write("  private " + tn + " prop_" + p.name() + ";\n");
 143.533 +                w.write("  public " + tn + " " + gs[0] + "() {\n");
 143.534 +                w.write("    proto.verifyUnlocked();\n");
 143.535 +                w.write("    return prop_" + p.name() + ";\n");
 143.536 +                w.write("  }\n");
 143.537 +                w.write("  public void " + gs[1] + "(" + tn + " v) {\n");
 143.538 +                w.write("    proto.verifyUnlocked();\n");
 143.539 +                w.write("    if (TYPE.isSame(prop_" + p.name() + ", v)) return;\n");
 143.540 +                w.write("    prop_" + p.name() + " = v;\n");
 143.541 +                w.write("    proto.valueHasMutated(\"" + p.name() + "\");\n");
 143.542 +                Collection<String> dependants = deps.get(p.name());
 143.543 +                if (dependants != null) {
 143.544 +                    for (String depProp : dependants) {
 143.545 +                        w.write("    proto.valueHasMutated(\"" + depProp + "\");\n");
 143.546 +                    }
 143.547 +                }
 143.548 +                dependants = functionDeps.get(p.name());
 143.549 +                if (dependants != null) {
 143.550 +                    w.append(className).append(" model = ").append(className).append(".this;\n");
 143.551 +                    for (String call : dependants) {
 143.552 +                        w.append("  ").append(call);
 143.553 +                    }
 143.554 +                }
 143.555 +                w.write("  }\n");
 143.556 +            }
 143.557 +            
 143.558 +            props.add(p.name());
 143.559 +            props.add(gs[2]);
 143.560 +            props.add(gs[3]);
 143.561 +            props.add(gs[0]);
 143.562 +            props.add(castTo);
 143.563 +        }
 143.564 +        return ok;
 143.565 +    }
 143.566 +
 143.567 +    private boolean generateComputedProperties(
 143.568 +        Writer w, Prprt[] fixedProps,
 143.569 +        Collection<? extends Element> arr, Collection<String> props,
 143.570 +        Map<String,Collection<String>> deps
 143.571 +    ) throws IOException {
 143.572 +        boolean ok = true;
 143.573 +        for (Element e : arr) {
 143.574 +            if (e.getKind() != ElementKind.METHOD) {
 143.575 +                continue;
 143.576 +            }
 143.577 +            if (e.getAnnotation(ComputedProperty.class) == null) {
 143.578 +                continue;
 143.579 +            }
 143.580 +            if (!e.getModifiers().contains(Modifier.STATIC)) {
 143.581 +                error("Method " + e.getSimpleName() + " has to be static when annotated by @ComputedProperty", e);
 143.582 +                ok = false;
 143.583 +                continue;
 143.584 +            }
 143.585 +            ExecutableElement ee = (ExecutableElement)e;
 143.586 +            final TypeMirror rt = ee.getReturnType();
 143.587 +            final Types tu = processingEnv.getTypeUtils();
 143.588 +            TypeMirror ert = tu.erasure(rt);
 143.589 +            String tn = fqn(ert, ee);
 143.590 +            boolean array = false;
 143.591 +            final TypeMirror toCheck;
 143.592 +            if (tn.equals("java.util.List")) {
 143.593 +                array = true;
 143.594 +                toCheck = ((DeclaredType)rt).getTypeArguments().get(0);
 143.595 +            } else {
 143.596 +                toCheck = rt;
 143.597 +            }
 143.598 +            
 143.599 +            final String sn = ee.getSimpleName().toString();
 143.600 +            
 143.601 +            if (toCheck.getKind().isPrimitive()) {
 143.602 +                // OK
 143.603 +            } else {
 143.604 +                TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
 143.605 +                TypeMirror enumType = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType();
 143.606 +
 143.607 +                if (tu.isSubtype(toCheck, stringType)) {
 143.608 +                    // OK
 143.609 +                } else if (tu.isSubtype(tu.erasure(toCheck), tu.erasure(enumType))) {
 143.610 +                    // OK
 143.611 +                } else if (isModel(toCheck)) {
 143.612 +                    // OK
 143.613 +                } else {
 143.614 +                    ok = false;
 143.615 +                    error(sn + " cannot return " + toCheck, e);
 143.616 +                }
 143.617 +            }
 143.618 +            
 143.619 +            String[] gs = toGetSet(sn, tn, array);
 143.620 +            
 143.621 +            w.write("  public " + tn + " " + gs[0] + "() {\n");
 143.622 +            int arg = 0;
 143.623 +            for (VariableElement pe : ee.getParameters()) {
 143.624 +                final String dn = pe.getSimpleName().toString();
 143.625 +                
 143.626 +                if (!verifyPropName(pe, dn, fixedProps)) {
 143.627 +                    ok = false;
 143.628 +                }
 143.629 +                
 143.630 +                final String dt = fqn(pe.asType(), ee);
 143.631 +                String[] call = toGetSet(dn, dt, false);
 143.632 +                w.write("    " + dt + " arg" + (++arg) + " = ");
 143.633 +                w.write(call[0] + "();\n");
 143.634 +                
 143.635 +                Collection<String> depends = deps.get(dn);
 143.636 +                if (depends == null) {
 143.637 +                    depends = new LinkedHashSet<String>();
 143.638 +                    deps.put(dn, depends);
 143.639 +                }
 143.640 +                depends.add(sn);
 143.641 +            }
 143.642 +            w.write("    try {\n");
 143.643 +            w.write("      proto.acquireLock();\n");
 143.644 +            w.write("      return " + fqn(ee.getEnclosingElement().asType(), ee) + '.' + e.getSimpleName() + "(");
 143.645 +            String sep = "";
 143.646 +            for (int i = 1; i <= arg; i++) {
 143.647 +                w.write(sep);
 143.648 +                w.write("arg" + i);
 143.649 +                sep = ", ";
 143.650 +            }
 143.651 +            w.write(");\n");
 143.652 +            w.write("    } finally {\n");
 143.653 +            w.write("      proto.releaseLock();\n");
 143.654 +            w.write("    }\n");
 143.655 +            w.write("  }\n");
 143.656 +
 143.657 +            props.add(e.getSimpleName().toString());
 143.658 +            props.add(gs[2]);
 143.659 +            props.add(null);
 143.660 +            props.add(gs[0]);
 143.661 +            props.add(tn);
 143.662 +        }
 143.663 +        
 143.664 +        return ok;
 143.665 +    }
 143.666 +
 143.667 +    private static String[] toGetSet(String name, String type, boolean array) {
 143.668 +        String n = Character.toUpperCase(name.charAt(0)) + name.substring(1);
 143.669 +        String bck2brwsrType = "L" + type.replace('.', '_') + "_2";
 143.670 +        if ("int".equals(type)) {
 143.671 +            bck2brwsrType = "I";
 143.672 +        }
 143.673 +        if ("double".equals(type)) {
 143.674 +            bck2brwsrType = "D";
 143.675 +        }
 143.676 +        String pref = "get";
 143.677 +        if ("boolean".equals(type)) {
 143.678 +            pref = "is";
 143.679 +            bck2brwsrType = "Z";
 143.680 +        }
 143.681 +        final String nu = n.replace('.', '_');
 143.682 +        if (array) {
 143.683 +            return new String[] { 
 143.684 +                "get" + n,
 143.685 +                null,
 143.686 +                "get" + nu + "__Ljava_util_List_2",
 143.687 +                null
 143.688 +            };
 143.689 +        }
 143.690 +        return new String[]{
 143.691 +            pref + n, 
 143.692 +            "set" + n, 
 143.693 +            pref + nu + "__" + bck2brwsrType,
 143.694 +            "set" + nu + "__V" + bck2brwsrType
 143.695 +        };
 143.696 +    }
 143.697 +
 143.698 +    private String typeName(Element where, Prprt p) {
 143.699 +        String ret;
 143.700 +        boolean[] isModel = { false };
 143.701 +        boolean[] isEnum = { false };
 143.702 +        boolean isPrimitive[] = { false };
 143.703 +        ret = checkType(p, isModel, isEnum, isPrimitive);
 143.704 +        if (p.array()) {
 143.705 +            String bt = findBoxedType(ret);
 143.706 +            if (bt != null) {
 143.707 +                return bt;
 143.708 +            }
 143.709 +        }
 143.710 +        return ret;
 143.711 +    }
 143.712 +    
 143.713 +    private static String findBoxedType(String ret) {
 143.714 +        if (ret.equals("boolean")) {
 143.715 +            return Boolean.class.getName();
 143.716 +        }
 143.717 +        if (ret.equals("byte")) {
 143.718 +            return Byte.class.getName();
 143.719 +        }
 143.720 +        if (ret.equals("short")) {
 143.721 +            return Short.class.getName();
 143.722 +        }
 143.723 +        if (ret.equals("char")) {
 143.724 +            return Character.class.getName();
 143.725 +        }
 143.726 +        if (ret.equals("int")) {
 143.727 +            return Integer.class.getName();
 143.728 +        }
 143.729 +        if (ret.equals("long")) {
 143.730 +            return Long.class.getName();
 143.731 +        }
 143.732 +        if (ret.equals("float")) {
 143.733 +            return Float.class.getName();
 143.734 +        }
 143.735 +        if (ret.equals("double")) {
 143.736 +            return Double.class.getName();
 143.737 +        }
 143.738 +        return null;
 143.739 +    }
 143.740 +
 143.741 +    private boolean verifyPropName(Element e, String propName, Prprt[] existingProps) {
 143.742 +        StringBuilder sb = new StringBuilder();
 143.743 +        String sep = "";
 143.744 +        for (Prprt Prprt : existingProps) {
 143.745 +            if (Prprt.name().equals(propName)) {
 143.746 +                return true;
 143.747 +            }
 143.748 +            sb.append(sep);
 143.749 +            sb.append('"');
 143.750 +            sb.append(Prprt.name());
 143.751 +            sb.append('"');
 143.752 +            sep = ", ";
 143.753 +        }
 143.754 +        error(
 143.755 +            propName + " is not one of known properties: " + sb
 143.756 +            , e
 143.757 +        );
 143.758 +        return false;
 143.759 +    }
 143.760 +
 143.761 +    private static String findPkgName(Element e) {
 143.762 +        for (;;) {
 143.763 +            if (e.getKind() == ElementKind.PACKAGE) {
 143.764 +                return ((PackageElement)e).getQualifiedName().toString();
 143.765 +            }
 143.766 +            e = e.getEnclosingElement();
 143.767 +        }
 143.768 +    }
 143.769 +
 143.770 +    private boolean generateFunctions(
 143.771 +        Element clazz, StringWriter body, String className, 
 143.772 +        List<? extends Element> enclosedElements, List<String> functions
 143.773 +    ) {
 143.774 +        for (Element m : enclosedElements) {
 143.775 +            if (m.getKind() != ElementKind.METHOD) {
 143.776 +                continue;
 143.777 +            }
 143.778 +            ExecutableElement e = (ExecutableElement)m;
 143.779 +            Function onF = e.getAnnotation(Function.class);
 143.780 +            if (onF == null) {
 143.781 +                continue;
 143.782 +            }
 143.783 +            if (!e.getModifiers().contains(Modifier.STATIC)) {
 143.784 +                error("@OnFunction method needs to be static", e);
 143.785 +                return false;
 143.786 +            }
 143.787 +            if (e.getModifiers().contains(Modifier.PRIVATE)) {
 143.788 +                error("@OnFunction method cannot be private", e);
 143.789 +                return false;
 143.790 +            }
 143.791 +            if (e.getReturnType().getKind() != TypeKind.VOID) {
 143.792 +                error("@OnFunction method should return void", e);
 143.793 +                return false;
 143.794 +            }
 143.795 +            String n = e.getSimpleName().toString();
 143.796 +            body.append("  private void ").append(n).append("(Object data, Object ev) {\n");
 143.797 +            body.append("    ").append(((TypeElement)clazz).getQualifiedName()).append(".").append(n).append("(");
 143.798 +            body.append(wrapParams(e, null, className, "ev", "data"));
 143.799 +            body.append(");\n");
 143.800 +            body.append("  }\n");
 143.801 +            
 143.802 +            functions.add(n);
 143.803 +            functions.add(n + "__VLjava_lang_Object_2Ljava_lang_Object_2");
 143.804 +        }
 143.805 +        return true;
 143.806 +    }
 143.807 +
 143.808 +    private boolean generateOnChange(Element clazz, Map<String,Collection<String>> propDeps,
 143.809 +        Prprt[] properties, String className, 
 143.810 +        Map<String, Collection<String>> functionDeps
 143.811 +    ) {
 143.812 +        for (Element m : clazz.getEnclosedElements()) {
 143.813 +            if (m.getKind() != ElementKind.METHOD) {
 143.814 +                continue;
 143.815 +            }
 143.816 +            ExecutableElement e = (ExecutableElement) m;
 143.817 +            OnPropertyChange onPC = e.getAnnotation(OnPropertyChange.class);
 143.818 +            if (onPC == null) {
 143.819 +                continue;
 143.820 +            }
 143.821 +            for (String pn : onPC.value()) {
 143.822 +                if (findPrprt(properties, pn) == null && findDerivedFrom(propDeps, pn).isEmpty()) {
 143.823 +                    error("No Prprt named '" + pn + "' in the model", clazz);
 143.824 +                    return false;
 143.825 +                }
 143.826 +            }
 143.827 +            if (!e.getModifiers().contains(Modifier.STATIC)) {
 143.828 +                error("@OnPrprtChange method needs to be static", e);
 143.829 +                return false;
 143.830 +            }
 143.831 +            if (e.getModifiers().contains(Modifier.PRIVATE)) {
 143.832 +                error("@OnPrprtChange method cannot be private", e);
 143.833 +                return false;
 143.834 +            }
 143.835 +            if (e.getReturnType().getKind() != TypeKind.VOID) {
 143.836 +                error("@OnPrprtChange method should return void", e);
 143.837 +                return false;
 143.838 +            }
 143.839 +            String n = e.getSimpleName().toString();
 143.840 +            
 143.841 +            
 143.842 +            for (String pn : onPC.value()) {
 143.843 +                StringBuilder call = new StringBuilder();
 143.844 +                call.append("  ").append(clazz.getSimpleName()).append(".").append(n).append("(");
 143.845 +                call.append(wrapPropName(e, className, "name", pn));
 143.846 +                call.append(");\n");
 143.847 +                
 143.848 +                Collection<String> change = functionDeps.get(pn);
 143.849 +                if (change == null) {
 143.850 +                    change = new ArrayList<String>();
 143.851 +                    functionDeps.put(pn, change);
 143.852 +                }
 143.853 +                change.add(call.toString());
 143.854 +                for (String dpn : findDerivedFrom(propDeps, pn)) {
 143.855 +                    change = functionDeps.get(dpn);
 143.856 +                    if (change == null) {
 143.857 +                        change = new ArrayList<String>();
 143.858 +                        functionDeps.put(dpn, change);
 143.859 +                    }
 143.860 +                    change.add(call.toString());
 143.861 +                }
 143.862 +            }
 143.863 +        }
 143.864 +        return true;
 143.865 +    }
 143.866 +
 143.867 +    private boolean generateOperation(Element clazz, 
 143.868 +        StringWriter body, String className, 
 143.869 +        List<? extends Element> enclosedElements
 143.870 +    ) {
 143.871 +        for (Element m : enclosedElements) {
 143.872 +            if (m.getKind() != ElementKind.METHOD) {
 143.873 +                continue;
 143.874 +            }
 143.875 +            ExecutableElement e = (ExecutableElement)m;
 143.876 +            ModelOperation mO = e.getAnnotation(ModelOperation.class);
 143.877 +            if (mO == null) {
 143.878 +                continue;
 143.879 +            }
 143.880 +            if (!e.getModifiers().contains(Modifier.STATIC)) {
 143.881 +                error("@ModelOperation method needs to be static", e);
 143.882 +                return false;
 143.883 +            }
 143.884 +            if (e.getModifiers().contains(Modifier.PRIVATE)) {
 143.885 +                error("@ModelOperation method cannot be private", e);
 143.886 +                return false;
 143.887 +            }
 143.888 +            if (e.getReturnType().getKind() != TypeKind.VOID) {
 143.889 +                error("@ModelOperation method should return void", e);
 143.890 +                return false;
 143.891 +            }
 143.892 +            List<String> args = new ArrayList<String>();
 143.893 +            {
 143.894 +                body.append("  public void ").append(m.getSimpleName()).append("(");
 143.895 +                String sep = "";
 143.896 +                boolean checkFirst = true;
 143.897 +                for (VariableElement ve : e.getParameters()) {
 143.898 +                    final TypeMirror type = ve.asType();
 143.899 +                    CharSequence simpleName;
 143.900 +                    if (type.getKind() == TypeKind.DECLARED) {
 143.901 +                        simpleName = ((DeclaredType)type).asElement().getSimpleName();
 143.902 +                    } else {
 143.903 +                        simpleName = type.toString();
 143.904 +                    }
 143.905 +                    if (simpleName.toString().equals(className)) {
 143.906 +                        checkFirst = false;
 143.907 +                    } else {
 143.908 +                        if (checkFirst) {
 143.909 +                            error("First parameter of @ModelOperation method must be " + className, m);
 143.910 +                            return false;
 143.911 +                        }
 143.912 +                        args.add(ve.getSimpleName().toString());
 143.913 +                        body.append(sep).append("final ");
 143.914 +                        body.append(ve.asType().toString()).append(" ");
 143.915 +                        body.append(ve.toString());
 143.916 +                        sep = ", ";
 143.917 +                    }
 143.918 +                }
 143.919 +                body.append(") {\n");
 143.920 +                body.append("    proto.runInBrowser(new Runnable() { public void run() {\n");
 143.921 +                body.append("      ").append(clazz.getSimpleName()).append(".").append(m.getSimpleName()).append("(");
 143.922 +                body.append(className).append(".this");
 143.923 +                for (String s : args) {
 143.924 +                    body.append(", ").append(s);
 143.925 +                }
 143.926 +                body.append(");\n");
 143.927 +                body.append("    }});\n");
 143.928 +                body.append("  }\n");
 143.929 +            }
 143.930 +            
 143.931 +        }
 143.932 +        return true;
 143.933 +    }
 143.934 +    
 143.935 +    
 143.936 +    private boolean generateReceive(
 143.937 +        Element clazz, StringWriter body, String className, 
 143.938 +        List<? extends Element> enclosedElements, StringBuilder inType
 143.939 +    ) {
 143.940 +        inType.append("  @Override public void onMessage(").append(className).append(" model, int index, int type, Object data) {\n");
 143.941 +        inType.append("    switch (index) {\n");
 143.942 +        int index = 0;
 143.943 +        for (Element m : enclosedElements) {
 143.944 +            if (m.getKind() != ElementKind.METHOD) {
 143.945 +                continue;
 143.946 +            }
 143.947 +            ExecutableElement e = (ExecutableElement)m;
 143.948 +            OnReceive onR = e.getAnnotation(OnReceive.class);
 143.949 +            if (onR == null) {
 143.950 +                continue;
 143.951 +            }
 143.952 +            if (!e.getModifiers().contains(Modifier.STATIC)) {
 143.953 +                error("@OnReceive method needs to be static", e);
 143.954 +                return false;
 143.955 +            }
 143.956 +            if (e.getModifiers().contains(Modifier.PRIVATE)) {
 143.957 +                error("@OnReceive method cannot be private", e);
 143.958 +                return false;
 143.959 +            }
 143.960 +            if (e.getReturnType().getKind() != TypeKind.VOID) {
 143.961 +                error("@OnReceive method should return void", e);
 143.962 +                return false;
 143.963 +            }
 143.964 +            if (!onR.jsonp().isEmpty() && !"GET".equals(onR.method())) {
 143.965 +                error("JSONP works only with GET transport method", e);
 143.966 +            }
 143.967 +            String dataMirror = findDataSpecified(e, onR);
 143.968 +            if ("PUT".equals(onR.method()) && dataMirror == null) {
 143.969 +                error("PUT method needs to specify a data() class", e);
 143.970 +                return false;
 143.971 +            }
 143.972 +            if ("POST".equals(onR.method()) && dataMirror == null) {
 143.973 +                error("POST method needs to specify a data() class", e);
 143.974 +                return false;
 143.975 +            }
 143.976 +            String modelClass = null;
 143.977 +            boolean expectsList = false;
 143.978 +            List<String> args = new ArrayList<String>();
 143.979 +            {
 143.980 +                for (VariableElement ve : e.getParameters()) {
 143.981 +                    TypeMirror modelType = null;
 143.982 +                    final TypeMirror type = ve.asType();
 143.983 +                    CharSequence simpleName;
 143.984 +                    if (type.getKind() == TypeKind.DECLARED) {
 143.985 +                        simpleName = ((DeclaredType)type).asElement().getSimpleName();
 143.986 +                    } else {
 143.987 +                        simpleName = type.toString();
 143.988 +                    }
 143.989 +                    if (simpleName.toString().equals(className)) {
 143.990 +                        args.add("model");
 143.991 +                    } else if (isModel(ve.asType())) {
 143.992 +                        modelType = ve.asType();
 143.993 +                    } else if (ve.asType().getKind() == TypeKind.ARRAY) {
 143.994 +                        modelType = ((ArrayType)ve.asType()).getComponentType();
 143.995 +                        expectsList = true;
 143.996 +                    } else if (ve.asType().toString().equals("java.lang.String")) {
 143.997 +                        modelType = ve.asType();
 143.998 +                    }
 143.999 +                    if (modelType != null) {
143.1000 +                        if (modelClass != null) {
143.1001 +                            error("There can be only one model class among arguments", e);
143.1002 +                        } else {
143.1003 +                            modelClass = modelType.toString();
143.1004 +                            if (expectsList) {
143.1005 +                                args.add("arr");
143.1006 +                            } else {
143.1007 +                                args.add("arr[0]");
143.1008 +                            }
143.1009 +                        }
143.1010 +                    }
143.1011 +                }
143.1012 +            }
143.1013 +            if (modelClass == null) {
143.1014 +                error("The method needs to have one @Model class as parameter", e);
143.1015 +            }
143.1016 +            String n = e.getSimpleName().toString();
143.1017 +            if ("WebSocket".equals(onR.method())) {
143.1018 +                body.append("  /** Performs WebSocket communication. Call with <code>null</code> data parameter\n");
143.1019 +                body.append("  * to open the connection (even if not required). Call with non-null data to\n");
143.1020 +                body.append("  * send messages to server. Call again with <code>null</code> data to close the socket.\n");
143.1021 +                body.append("  */\n");
143.1022 +            }
143.1023 +            body.append("  public void ").append(n).append("(");
143.1024 +            StringBuilder urlBefore = new StringBuilder();
143.1025 +            StringBuilder urlAfter = new StringBuilder();
143.1026 +            String jsonpVarName = null;
143.1027 +            {
143.1028 +                String sep = "";
143.1029 +                boolean skipJSONP = onR.jsonp().isEmpty();
143.1030 +                for (String p : findParamNames(e, onR.url(), onR.jsonp(), urlBefore, urlAfter)) {
143.1031 +                    if (!skipJSONP && p.equals(onR.jsonp())) {
143.1032 +                        skipJSONP = true;
143.1033 +                        jsonpVarName = p;
143.1034 +                        continue;
143.1035 +                    }
143.1036 +                    body.append(sep);
143.1037 +                    body.append("String ").append(p);
143.1038 +                    sep = ", ";
143.1039 +                }
143.1040 +                if (!skipJSONP) {
143.1041 +                    error(
143.1042 +                        "Name of jsonp attribute ('" + onR.jsonp() + 
143.1043 +                        "') is not used in url attribute '" + onR.url() + "'", e
143.1044 +                    );
143.1045 +                }
143.1046 +                if (dataMirror != null) {
143.1047 +                    body.append(sep).append(dataMirror.toString()).append(" data");
143.1048 +                }
143.1049 +            }
143.1050 +            body.append(") {\n");
143.1051 +            boolean webSocket = onR.method().equals("WebSocket");
143.1052 +            if (webSocket) {
143.1053 +                if (generateWSReceiveBody(index++, body, inType, onR, e, clazz, className, expectsList, modelClass, n, args, urlBefore, jsonpVarName, urlAfter, dataMirror)) {
143.1054 +                    return false;
143.1055 +                }
143.1056 +                body.append("  }\n");
143.1057 +                body.append("  private Object ws_" + e.getSimpleName() + ";\n");
143.1058 +            } else {
143.1059 +                if (generateJSONReceiveBody(index++, body, inType, onR, e, clazz, className, expectsList, modelClass, n, args, urlBefore, jsonpVarName, urlAfter, dataMirror)) {
143.1060 +                    return false;
143.1061 +                }
143.1062 +                body.append("  }\n");
143.1063 +            }
143.1064 +        }
143.1065 +        inType.append("    }\n");
143.1066 +        inType.append("    throw new UnsupportedOperationException(\"index: \" + index + \" type: \" + type);\n");
143.1067 +        inType.append("  }\n");
143.1068 +        return true;
143.1069 +    }
143.1070 +
143.1071 +    private boolean generateJSONReceiveBody(int index, StringWriter method, StringBuilder body, OnReceive onR, ExecutableElement e, Element clazz, String className, boolean expectsList, String modelClass, String n, List<String> args, StringBuilder urlBefore, String jsonpVarName, StringBuilder urlAfter, String dataMirror) {
143.1072 +        body.append(
143.1073 +            "    case " + index + ": {\n" +
143.1074 +            "      if (type == 2) { /* on error */\n" +
143.1075 +            "        Exception ex = (Exception)data;\n"
143.1076 +            );
143.1077 +        if (onR.onError().isEmpty()) {
143.1078 +            body.append(
143.1079 +                "        ex.printStackTrace();\n"
143.1080 +                );
143.1081 +        } else {
143.1082 +            if (!findOnError(e, ((TypeElement)clazz), onR.onError(), className)) {
143.1083 +                return true;
143.1084 +            }
143.1085 +            body.append("        ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
143.1086 +            body.append("model, ex);\n");
143.1087 +        }
143.1088 +        body.append(
143.1089 +            "        return;\n" +
143.1090 +            "      } else if (type == 1) {\n" +
143.1091 +            "        Object[] ev = (Object[])data;\n"
143.1092 +            );
143.1093 +        if (expectsList) {
143.1094 +            body.append(
143.1095 +                "        " + modelClass + "[] arr = new " + modelClass + "[ev.length];\n"
143.1096 +                );
143.1097 +        } else {
143.1098 +            body.append(
143.1099 +                "        " + modelClass + "[] arr = { null };\n"
143.1100 +                );
143.1101 +        }
143.1102 +        body.append(
143.1103 +            "        TYPE.copyJSON(model.proto.getContext(), ev, " + modelClass + ".class, arr);\n"
143.1104 +        );
143.1105 +        {
143.1106 +            body.append("        ").append(clazz.getSimpleName()).append(".").append(n).append("(");
143.1107 +            String sep = "";
143.1108 +            for (String arg : args) {
143.1109 +                body.append(sep);
143.1110 +                body.append(arg);
143.1111 +                sep = ", ";
143.1112 +            }
143.1113 +            body.append(");\n");
143.1114 +        }
143.1115 +        body.append(
143.1116 +            "        return;\n" +
143.1117 +            "      }\n" +
143.1118 +            "    }\n"
143.1119 +            );
143.1120 +        method.append("    proto.loadJSON(" + index + ",\n        ");
143.1121 +        method.append(urlBefore).append(", ");
143.1122 +        if (jsonpVarName != null) {
143.1123 +            method.append(urlAfter);
143.1124 +        } else {
143.1125 +            method.append("null");
143.1126 +        }
143.1127 +        if (!"GET".equals(onR.method()) || dataMirror != null) {
143.1128 +            method.append(", \"").append(onR.method()).append('"');
143.1129 +            if (dataMirror != null) {
143.1130 +                method.append(", data");
143.1131 +            } else {
143.1132 +                method.append(", null");
143.1133 +            }
143.1134 +        } else {
143.1135 +            method.append(", null, null");
143.1136 +        }
143.1137 +        method.append(");\n");
143.1138 +        return false;
143.1139 +    }
143.1140 +    
143.1141 +    private boolean generateWSReceiveBody(int index, StringWriter method, StringBuilder body, OnReceive onR, ExecutableElement e, Element clazz, String className, boolean expectsList, String modelClass, String n, List<String> args, StringBuilder urlBefore, String jsonpVarName, StringBuilder urlAfter, String dataMirror) {
143.1142 +        body.append(
143.1143 +            "    case " + index + ": {\n" +
143.1144 +            "      if (type == 0) { /* on open */\n" +
143.1145 +            "        ").append(clazz.getSimpleName()).append(".").append(n).append("(");
143.1146 +        {
143.1147 +            String sep = "";
143.1148 +            for (String arg : args) {
143.1149 +                body.append(sep);
143.1150 +                if (arg.startsWith("arr")) {
143.1151 +                    body.append("null");
143.1152 +                } else {
143.1153 +                    body.append(arg);
143.1154 +                }
143.1155 +                sep = ", ";
143.1156 +            }
143.1157 +        }
143.1158 +        body.append(");\n");
143.1159 +        body.append(
143.1160 +            "        return;\n" +
143.1161 +            "      } else if (type == 2) { /* on error */\n" +
143.1162 +            "        Exception value = (Exception)data;\n"
143.1163 +            );
143.1164 +        if (onR.onError().isEmpty()) {
143.1165 +            body.append(
143.1166 +                "        value.printStackTrace();\n"
143.1167 +                );
143.1168 +        } else {
143.1169 +            if (!findOnError(e, ((TypeElement)clazz), onR.onError(), className)) {
143.1170 +                return true;
143.1171 +            }
143.1172 +            body.append("        ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
143.1173 +            body.append("model, value);\n");
143.1174 +        }
143.1175 +        body.append(
143.1176 +            "        return;\n" +
143.1177 +            "      } else if (type == 1) {\n" +
143.1178 +            "        Object[] ev = (Object[])data;\n"
143.1179 +        );
143.1180 +        if (expectsList) {
143.1181 +            body.append(
143.1182 +                "        " + modelClass + "[] arr = new " + modelClass + "[ev.length];\n"
143.1183 +                );
143.1184 +        } else {
143.1185 +            body.append(
143.1186 +                "        " + modelClass + "[] arr = { null };\n"
143.1187 +                );
143.1188 +        }
143.1189 +        body.append(
143.1190 +            "        TYPE.copyJSON(model.proto.getContext(), ev, " + modelClass + ".class, arr);\n"
143.1191 +        );
143.1192 +        {
143.1193 +            body.append("        ").append(clazz.getSimpleName()).append(".").append(n).append("(");
143.1194 +            String sep = "";
143.1195 +            for (String arg : args) {
143.1196 +                body.append(sep);
143.1197 +                body.append(arg);
143.1198 +                sep = ", ";
143.1199 +            }
143.1200 +            body.append(");\n");
143.1201 +        }
143.1202 +        body.append(
143.1203 +            "        return;\n" +
143.1204 +            "      }"
143.1205 +        );
143.1206 +        if (!onR.onError().isEmpty()) {
143.1207 +            body.append(" else if (type == 3) { /* on close */\n");
143.1208 +            body.append("        ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
143.1209 +            body.append("model, null);\n");
143.1210 +            body.append(
143.1211 +                "        return;" +
143.1212 +                "      }"
143.1213 +            );
143.1214 +        }
143.1215 +        body.append("\n");
143.1216 +        body.append("    }\n");
143.1217 +        method.append("    if (this.ws_").append(e.getSimpleName()).append(" == null) {\n");
143.1218 +        method.append("      this.ws_").append(e.getSimpleName());
143.1219 +        method.append("= proto.wsOpen(" + index + ", ");
143.1220 +        method.append(urlBefore).append(", data);\n");
143.1221 +        method.append("    } else {\n");
143.1222 +        method.append("      proto.wsSend(this.ws_").append(e.getSimpleName()).append(", ").append(urlBefore).append(", data);\n");
143.1223 +        method.append("    }\n");
143.1224 +        return false;
143.1225 +    }
143.1226 +
143.1227 +    private CharSequence wrapParams(
143.1228 +        ExecutableElement ee, String id, String className, String evName, String dataName
143.1229 +    ) {
143.1230 +        TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
143.1231 +        StringBuilder params = new StringBuilder();
143.1232 +        boolean first = true;
143.1233 +        for (VariableElement ve : ee.getParameters()) {
143.1234 +            if (!first) {
143.1235 +                params.append(", ");
143.1236 +            }
143.1237 +            first = false;
143.1238 +            String toCall = null;
143.1239 +            String toFinish = null;
143.1240 +            boolean addNull = true;
143.1241 +            if (ve.asType() == stringType) {
143.1242 +                if (ve.getSimpleName().contentEquals("id")) {
143.1243 +                    params.append('"').append(id).append('"');
143.1244 +                    continue;
143.1245 +                }
143.1246 +                toCall = "proto.toString(";
143.1247 +            }
143.1248 +            if (ve.asType().getKind() == TypeKind.DOUBLE) {
143.1249 +                toCall = "proto.toNumber(";
143.1250 +                toFinish = ".doubleValue()";
143.1251 +            }
143.1252 +            if (ve.asType().getKind() == TypeKind.INT) {
143.1253 +                toCall = "proto.toNumber(";
143.1254 +                toFinish = ".intValue()";
143.1255 +            }
143.1256 +            if (dataName != null && ve.getSimpleName().contentEquals(dataName) && isModel(ve.asType())) {
143.1257 +                toCall = "proto.toModel(" + ve.asType() + ".class, ";
143.1258 +                addNull = false;
143.1259 +            }
143.1260 +
143.1261 +            if (toCall != null) {
143.1262 +                params.append(toCall);
143.1263 +                if (dataName != null && ve.getSimpleName().contentEquals(dataName)) {
143.1264 +                    params.append(dataName);
143.1265 +                    if (addNull) {
143.1266 +                        params.append(", null");
143.1267 +                    }
143.1268 +                } else {
143.1269 +                    if (evName == null) {
143.1270 +                        final StringBuilder sb = new StringBuilder();
143.1271 +                        sb.append("Unexpected string parameter name.");
143.1272 +                        if (dataName != null) {
143.1273 +                            sb.append(" Try \"").append(dataName).append("\"");
143.1274 +                        }
143.1275 +                        error(sb.toString(), ee);
143.1276 +                    }
143.1277 +                    params.append(evName);
143.1278 +                    params.append(", \"");
143.1279 +                    params.append(ve.getSimpleName().toString());
143.1280 +                    params.append("\"");
143.1281 +                }
143.1282 +                params.append(")");
143.1283 +                if (toFinish != null) {
143.1284 +                    params.append(toFinish);
143.1285 +                }
143.1286 +                continue;
143.1287 +            }
143.1288 +            String rn = fqn(ve.asType(), ee);
143.1289 +            int last = rn.lastIndexOf('.');
143.1290 +            if (last >= 0) {
143.1291 +                rn = rn.substring(last + 1);
143.1292 +            }
143.1293 +            if (rn.equals(className)) {
143.1294 +                params.append(className).append(".this");
143.1295 +                continue;
143.1296 +            }
143.1297 +            error(
143.1298 +                "The annotated method can only accept " + className + " argument or argument named 'data'",
143.1299 +                ee
143.1300 +            );
143.1301 +        }
143.1302 +        return params;
143.1303 +    }
143.1304 +    
143.1305 +    
143.1306 +    private CharSequence wrapPropName(
143.1307 +        ExecutableElement ee, String className, String propName, String propValue
143.1308 +    ) {
143.1309 +        TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
143.1310 +        StringBuilder params = new StringBuilder();
143.1311 +        boolean first = true;
143.1312 +        for (VariableElement ve : ee.getParameters()) {
143.1313 +            if (!first) {
143.1314 +                params.append(", ");
143.1315 +            }
143.1316 +            first = false;
143.1317 +            if (ve.asType() == stringType) {
143.1318 +                if (propName != null && ve.getSimpleName().contentEquals(propName)) {
143.1319 +                    params.append('"').append(propValue).append('"');
143.1320 +                } else {
143.1321 +                    error("Unexpected string parameter name. Try \"" + propName + "\".", ee);
143.1322 +                }
143.1323 +                continue;
143.1324 +            }
143.1325 +            String rn = fqn(ve.asType(), ee);
143.1326 +            int last = rn.lastIndexOf('.');
143.1327 +            if (last >= 0) {
143.1328 +                rn = rn.substring(last + 1);
143.1329 +            }
143.1330 +            if (rn.equals(className)) {
143.1331 +                params.append("model");
143.1332 +                continue;
143.1333 +            }
143.1334 +            error(
143.1335 +                "@OnPrprtChange method can only accept String or " + className + " arguments",
143.1336 +                ee);
143.1337 +        }
143.1338 +        return params;
143.1339 +    }
143.1340 +    
143.1341 +    private boolean isModel(TypeMirror tm) {
143.1342 +        if (tm.getKind() == TypeKind.ERROR) {
143.1343 +            return true;
143.1344 +        }
143.1345 +        final Element e = processingEnv.getTypeUtils().asElement(tm);
143.1346 +        if (e == null) {
143.1347 +            return false;
143.1348 +        }
143.1349 +        for (Element ch : e.getEnclosedElements()) {
143.1350 +            if (ch.getKind() == ElementKind.METHOD) {
143.1351 +                ExecutableElement ee = (ExecutableElement)ch;
143.1352 +                if (ee.getParameters().isEmpty() && ee.getSimpleName().contentEquals("modelFor")) {
143.1353 +                    return true;
143.1354 +                }
143.1355 +            }
143.1356 +        }
143.1357 +        return models.values().contains(e.getSimpleName().toString());
143.1358 +    }
143.1359 +    
143.1360 +    private void writeToString(Prprt[] props, Writer w) throws IOException {
143.1361 +        w.write("  public String toString() {\n");
143.1362 +        w.write("    StringBuilder sb = new StringBuilder();\n");
143.1363 +        w.write("    sb.append('{');\n");
143.1364 +        String sep = "";
143.1365 +        for (Prprt p : props) {
143.1366 +            w.write(sep);
143.1367 +            w.append("    sb.append('\"').append(\"" + p.name() + "\")");
143.1368 +                w.append(".append('\"').append(\":\");\n");
143.1369 +            w.append("    sb.append(TYPE.toJSON(prop_");
143.1370 +            w.append(p.name()).append("));\n");
143.1371 +            sep =    "    sb.append(',');\n";
143.1372 +        }
143.1373 +        w.write("    sb.append('}');\n");
143.1374 +        w.write("    return sb.toString();\n");
143.1375 +        w.write("  }\n");
143.1376 +    }
143.1377 +    private void writeClone(String className, Prprt[] props, Writer w) throws IOException {
143.1378 +        w.write("  public " + className + " clone() {\n");
143.1379 +        w.write("    return clone(proto.getContext());\n");
143.1380 +        w.write("  }\n");
143.1381 +        w.write("  private " + className + " clone(net.java.html.BrwsrCtx ctx) {\n");
143.1382 +        w.write("    " + className + " ret = new " + className + "(ctx);\n");
143.1383 +        for (Prprt p : props) {
143.1384 +            if (!p.array()) {
143.1385 +                boolean isModel[] = { false };
143.1386 +                boolean isEnum[] = { false };
143.1387 +                boolean isPrimitive[] = { false };
143.1388 +                checkType(p, isModel, isEnum, isPrimitive);
143.1389 +                if (!isModel[0]) {
143.1390 +                    w.write("    ret.prop_" + p.name() + " = prop_" + p.name() + ";\n");
143.1391 +                    continue;
143.1392 +                }
143.1393 +                w.write("    ret.prop_" + p.name() + " =  prop_" + p.name() + "  == null ? null : prop_" + p.name() + ".clone();\n");
143.1394 +            } else {
143.1395 +                w.write("    proto.cloneList(ret.prop_" + p.name() + ", ctx, prop_" + p.name() + ");\n");
143.1396 +            }
143.1397 +        }
143.1398 +        
143.1399 +        w.write("    return ret;\n");
143.1400 +        w.write("  }\n");
143.1401 +    }
143.1402 +
143.1403 +    private String inPckName(Element e) {
143.1404 +        StringBuilder sb = new StringBuilder();
143.1405 +        while (e.getKind() != ElementKind.PACKAGE) {
143.1406 +            if (sb.length() == 0) {
143.1407 +                sb.append(e.getSimpleName());
143.1408 +            } else {
143.1409 +                sb.insert(0, '.');
143.1410 +                sb.insert(0, e.getSimpleName());
143.1411 +            }
143.1412 +            e = e.getEnclosingElement();
143.1413 +        }
143.1414 +        return sb.toString();
143.1415 +    }
143.1416 +
143.1417 +    private String fqn(TypeMirror pt, Element relative) {
143.1418 +        if (pt.getKind() == TypeKind.ERROR) {
143.1419 +            final Elements eu = processingEnv.getElementUtils();
143.1420 +            PackageElement pckg = eu.getPackageOf(relative);
143.1421 +            return pckg.getQualifiedName() + "." + pt.toString();
143.1422 +        }
143.1423 +        return pt.toString();
143.1424 +    }
143.1425 +
143.1426 +    private String checkType(Prprt p, boolean[] isModel, boolean[] isEnum, boolean[] isPrimitive) {
143.1427 +        TypeMirror tm;
143.1428 +        try {
143.1429 +            String ret = p.typeName(processingEnv);
143.1430 +            TypeElement e = processingEnv.getElementUtils().getTypeElement(ret);
143.1431 +            if (e == null) {
143.1432 +                isModel[0] = true;
143.1433 +                isEnum[0] = false;
143.1434 +                isPrimitive[0] = false;
143.1435 +                return ret;
143.1436 +            }
143.1437 +            tm = e.asType();
143.1438 +        } catch (MirroredTypeException ex) {
143.1439 +            tm = ex.getTypeMirror();
143.1440 +        }
143.1441 +        tm = processingEnv.getTypeUtils().erasure(tm);
143.1442 +        if (isPrimitive[0] = tm.getKind().isPrimitive()) {
143.1443 +            isEnum[0] = false;
143.1444 +            isModel[0] = false;
143.1445 +            return tm.toString();
143.1446 +        }
143.1447 +        final Element e = processingEnv.getTypeUtils().asElement(tm);
143.1448 +        if (e.getKind() == ElementKind.CLASS && tm.getKind() == TypeKind.ERROR) {
143.1449 +            isModel[0] = true;
143.1450 +            isEnum[0] = false;
143.1451 +            return e.getSimpleName().toString();
143.1452 +        }
143.1453 +        
143.1454 +        final Model m = e == null ? null : e.getAnnotation(Model.class);
143.1455 +        String ret;
143.1456 +        if (m != null) {
143.1457 +            ret = findPkgName(e) + '.' + m.className();
143.1458 +            isModel[0] = true;
143.1459 +            models.put(e, m.className());
143.1460 +        } else if (findModelForMthd(e)) {
143.1461 +            ret = ((TypeElement)e).getQualifiedName().toString();
143.1462 +            isModel[0] = true;
143.1463 +        } else {
143.1464 +            ret = tm.toString();
143.1465 +        }
143.1466 +        TypeMirror enm = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType();
143.1467 +        enm = processingEnv.getTypeUtils().erasure(enm);
143.1468 +        isEnum[0] = processingEnv.getTypeUtils().isSubtype(tm, enm);
143.1469 +        return ret;
143.1470 +    }
143.1471 +    
143.1472 +    private static boolean findModelForMthd(Element clazz) {
143.1473 +        if (clazz == null) {
143.1474 +            return false;
143.1475 +        }
143.1476 +        for (Element e : clazz.getEnclosedElements()) {
143.1477 +            if (e.getKind() == ElementKind.METHOD) {
143.1478 +                ExecutableElement ee = (ExecutableElement)e;
143.1479 +                if (
143.1480 +                    ee.getSimpleName().contentEquals("modelFor") &&
143.1481 +                    ee.getParameters().isEmpty()
143.1482 +                ) {
143.1483 +                    return true;
143.1484 +                }
143.1485 +            }
143.1486 +        }
143.1487 +        return false;
143.1488 +    }
143.1489 +
143.1490 +    private Iterable<String> findParamNames(
143.1491 +        Element e, String url, String jsonParam, StringBuilder... both
143.1492 +    ) {
143.1493 +        List<String> params = new ArrayList<String>();
143.1494 +        int wasJSON = 0;
143.1495 +
143.1496 +        for (int pos = 0; ;) {
143.1497 +            int next = url.indexOf('{', pos);
143.1498 +            if (next == -1) {
143.1499 +                both[wasJSON].append('"')
143.1500 +                    .append(url.substring(pos))
143.1501 +                    .append('"');
143.1502 +                return params;
143.1503 +            }
143.1504 +            int close = url.indexOf('}', next);
143.1505 +            if (close == -1) {
143.1506 +                error("Unbalanced '{' and '}' in " + url, e);
143.1507 +                return params;
143.1508 +            }
143.1509 +            final String paramName = url.substring(next + 1, close);
143.1510 +            params.add(paramName);
143.1511 +            if (paramName.equals(jsonParam) && !jsonParam.isEmpty()) {
143.1512 +                both[wasJSON].append('"')
143.1513 +                    .append(url.substring(pos, next))
143.1514 +                    .append('"');
143.1515 +                wasJSON = 1;
143.1516 +            } else {
143.1517 +                both[wasJSON].append('"')
143.1518 +                    .append(url.substring(pos, next))
143.1519 +                    .append("\" + ").append(paramName).append(" + ");
143.1520 +            }
143.1521 +            pos = close + 1;
143.1522 +        }
143.1523 +    }
143.1524 +
143.1525 +    private static Prprt findPrprt(Prprt[] properties, String propName) {
143.1526 +        for (Prprt p : properties) {
143.1527 +            if (propName.equals(p.name())) {
143.1528 +                return p;
143.1529 +            }
143.1530 +        }
143.1531 +        return null;
143.1532 +    }
143.1533 +
143.1534 +    private boolean isPrimitive(String type) {
143.1535 +        return 
143.1536 +            "int".equals(type) ||
143.1537 +            "double".equals(type) ||
143.1538 +            "long".equals(type) ||
143.1539 +            "short".equals(type) ||
143.1540 +            "byte".equals(type) ||
143.1541 +            "char".equals(type) ||
143.1542 +            "boolean".equals(type) ||
143.1543 +            "float".equals(type);
143.1544 +    }
143.1545 +
143.1546 +    private static Collection<String> findDerivedFrom(Map<String, Collection<String>> propsDeps, String derivedProp) {
143.1547 +        Set<String> names = new HashSet<String>();
143.1548 +        for (Map.Entry<String, Collection<String>> e : propsDeps.entrySet()) {
143.1549 +            if (e.getValue().contains(derivedProp)) {
143.1550 +                names.add(e.getKey());
143.1551 +            }
143.1552 +        }
143.1553 +        return names;
143.1554 +    }
143.1555 +    
143.1556 +    private Prprt[] createProps(Element e, Property[] arr) {
143.1557 +        Prprt[] ret = Prprt.wrap(processingEnv, e, arr);
143.1558 +        Prprt[] prev = verify.put(e, ret);
143.1559 +        if (prev != null) {
143.1560 +            error("Two sets of properties for ", e);
143.1561 +        }
143.1562 +        return ret;
143.1563 +    }
143.1564 +    
143.1565 +    private static String strip(String s) {
143.1566 +        int indx = s.indexOf("__");
143.1567 +        if (indx >= 0) {
143.1568 +            return s.substring(0, indx);
143.1569 +        } else {
143.1570 +            return s;
143.1571 +        }
143.1572 +    }
143.1573 +
143.1574 +    private String findDataSpecified(ExecutableElement e, OnReceive onR) {
143.1575 +        try {
143.1576 +            return onR.data().getName();
143.1577 +        } catch (MirroredTypeException ex) {
143.1578 +            final TypeMirror tm = ex.getTypeMirror();
143.1579 +            String name;
143.1580 +            final Element te = processingEnv.getTypeUtils().asElement(tm);
143.1581 +            if (te.getKind() == ElementKind.CLASS && tm.getKind() == TypeKind.ERROR) {
143.1582 +                name = te.getSimpleName().toString();
143.1583 +            } else {
143.1584 +                name = tm.toString();
143.1585 +            }
143.1586 +            return "java.lang.Object".equals(name) ? null : name;
143.1587 +        } catch (Exception ex) {
143.1588 +            // fallback
143.1589 +        }
143.1590 +        
143.1591 +        AnnotationMirror found = null;
143.1592 +        for (AnnotationMirror am : e.getAnnotationMirrors()) {
143.1593 +            if (am.getAnnotationType().toString().equals(OnReceive.class.getName())) {
143.1594 +                found = am;
143.1595 +            }
143.1596 +        }
143.1597 +        if (found == null) {
143.1598 +            return null;
143.1599 +        }
143.1600 +        
143.1601 +        for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : found.getElementValues().entrySet()) {
143.1602 +            ExecutableElement ee = entry.getKey();
143.1603 +            AnnotationValue av = entry.getValue();
143.1604 +            if (ee.getSimpleName().contentEquals("data")) {
143.1605 +                List<? extends Object> values = getAnnoValues(processingEnv, e, found);
143.1606 +                for (Object v : values) {
143.1607 +                    String sv = v.toString();
143.1608 +                    if (sv.startsWith("data = ") && sv.endsWith(".class")) {
143.1609 +                        return sv.substring(7, sv.length() - 6);
143.1610 +                    }
143.1611 +                }
143.1612 +                return "error";
143.1613 +            }
143.1614 +        }
143.1615 +        return null;
143.1616 +    }
143.1617 +
143.1618 +    static List<? extends Object> getAnnoValues(ProcessingEnvironment pe, Element e, AnnotationMirror am) {
143.1619 +        try {
143.1620 +            Class<?> trees = Class.forName("com.sun.tools.javac.api.JavacTrees");
143.1621 +            Method m = trees.getMethod("instance", ProcessingEnvironment.class);
143.1622 +            Object instance = m.invoke(null, pe);
143.1623 +            m = instance.getClass().getMethod("getPath", Element.class, AnnotationMirror.class);
143.1624 +            Object path = m.invoke(instance, e, am);
143.1625 +            m = path.getClass().getMethod("getLeaf");
143.1626 +            Object leaf = m.invoke(path);
143.1627 +            m = leaf.getClass().getMethod("getArguments");
143.1628 +            return (List) m.invoke(leaf);
143.1629 +        } catch (Exception ex) {
143.1630 +            return Collections.emptyList();
143.1631 +        }
143.1632 +    }
143.1633 +
143.1634 +    private static class Prprt {
143.1635 +        private final Element e;
143.1636 +        private final AnnotationMirror tm;
143.1637 +        private final Property p;
143.1638 +
143.1639 +        public Prprt(Element e, AnnotationMirror tm, Property p) {
143.1640 +            this.e = e;
143.1641 +            this.tm = tm;
143.1642 +            this.p = p;
143.1643 +        }
143.1644 +        
143.1645 +        String name() {
143.1646 +            return p.name();
143.1647 +        }
143.1648 +        
143.1649 +        boolean array() {
143.1650 +            return p.array();
143.1651 +        }
143.1652 +
143.1653 +        String typeName(ProcessingEnvironment env) {
143.1654 +            RuntimeException ex;
143.1655 +            try {
143.1656 +                return p.type().getName();
143.1657 +            } catch (IncompleteAnnotationException e) {
143.1658 +                ex = e;
143.1659 +            } catch (AnnotationTypeMismatchException e) {
143.1660 +                ex = e;
143.1661 +            }
143.1662 +            for (Object v : getAnnoValues(env, e, tm)) {
143.1663 +                String s = v.toString().replace(" ", "");
143.1664 +                if (s.startsWith("type=") && s.endsWith(".class")) {
143.1665 +                    return s.substring(5, s.length() - 6);
143.1666 +                }
143.1667 +            }
143.1668 +            throw ex;
143.1669 +        }
143.1670 +        
143.1671 +        
143.1672 +        static Prprt[] wrap(ProcessingEnvironment pe, Element e, Property[] arr) {
143.1673 +            if (arr.length == 0) {
143.1674 +                return new Prprt[0];
143.1675 +            }
143.1676 +            
143.1677 +            if (e.getKind() != ElementKind.CLASS) {
143.1678 +                throw new IllegalStateException("" + e.getKind());
143.1679 +            }
143.1680 +            TypeElement te = (TypeElement)e;
143.1681 +            List<? extends AnnotationValue> val = null;
143.1682 +            for (AnnotationMirror an : te.getAnnotationMirrors()) {
143.1683 +                for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : an.getElementValues().entrySet()) {
143.1684 +                    if (entry.getKey().getSimpleName().contentEquals("properties")) {
143.1685 +                        val = (List)entry.getValue().getValue();
143.1686 +                        break;
143.1687 +                    }
143.1688 +                }
143.1689 +            }
143.1690 +            if (val == null || val.size() != arr.length) {
143.1691 +                pe.getMessager().printMessage(Diagnostic.Kind.ERROR, "" + val, e);
143.1692 +                return new Prprt[0];
143.1693 +            }
143.1694 +            Prprt[] ret = new Prprt[arr.length];
143.1695 +            BIG: for (int i = 0; i < ret.length; i++) {
143.1696 +                AnnotationMirror am = (AnnotationMirror)val.get(i).getValue();
143.1697 +                ret[i] = new Prprt(e, am, arr[i]);
143.1698 +                
143.1699 +            }
143.1700 +            return ret;
143.1701 +        }
143.1702 +    }
143.1703 +
143.1704 +    @Override
143.1705 +    public Iterable<? extends Completion> getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) {
143.1706 +        final Level l = Level.FINE;
143.1707 +        LOG.log(l, " element: {0}", element);
143.1708 +        LOG.log(l, " annotation: {0}", annotation);
143.1709 +        LOG.log(l, " member: {0}", member);
143.1710 +        LOG.log(l, " userText: {0}", userText);
143.1711 +        LOG.log(l, "str: {0}", annotation.getAnnotationType().toString());
143.1712 +        if (annotation.getAnnotationType().toString().equals(OnReceive.class.getName())) {
143.1713 +            if (member.getSimpleName().contentEquals("method")) {
143.1714 +                return Arrays.asList(
143.1715 +                    methodOf("GET"),
143.1716 +                    methodOf("POST"),
143.1717 +                    methodOf("PUT"),
143.1718 +                    methodOf("DELETE"),
143.1719 +                    methodOf("HEAD"),
143.1720 +                    methodOf("WebSocket")
143.1721 +                );
143.1722 +            }
143.1723 +        }
143.1724 +        
143.1725 +        return super.getCompletions(element, annotation, member, userText);
143.1726 +    }
143.1727 +    
143.1728 +    private static final Completion methodOf(String method) {
143.1729 +        ResourceBundle rb = ResourceBundle.getBundle("org.netbeans.html.json.impl.Bundle");
143.1730 +        return Completions.of('"' + method + '"', rb.getString("MSG_Completion_" + method));
143.1731 +    }
143.1732 +    
143.1733 +    private boolean findOnError(ExecutableElement errElem, TypeElement te, String name, String className) {
143.1734 +        String err = null;
143.1735 +        METHODS:
143.1736 +        for (Element e : te.getEnclosedElements()) {
143.1737 +            if (e.getKind() != ElementKind.METHOD) {
143.1738 +                continue;
143.1739 +            }
143.1740 +            if (!e.getSimpleName().contentEquals(name)) {
143.1741 +                continue;
143.1742 +            }
143.1743 +            if (!e.getModifiers().contains(Modifier.STATIC)) {
143.1744 +                errElem = (ExecutableElement) e;
143.1745 +                err = "Would have to be static";
143.1746 +                continue;
143.1747 +            }
143.1748 +            ExecutableElement ee = (ExecutableElement) e;
143.1749 +            TypeMirror excType = processingEnv.getElementUtils().getTypeElement(Exception.class.getName()).asType();
143.1750 +            final List<? extends VariableElement> params = ee.getParameters();
143.1751 +            boolean error = false;
143.1752 +            if (params.size() != 2) {
143.1753 +                error = true;
143.1754 +            } else {
143.1755 +                String firstType = params.get(0).asType().toString();
143.1756 +                int lastDot = firstType.lastIndexOf('.');
143.1757 +                if (lastDot != -1) {
143.1758 +                    firstType = firstType.substring(lastDot + 1);
143.1759 +                }
143.1760 +                if (!firstType.equals(className)) {
143.1761 +                    error = true;
143.1762 +                }
143.1763 +                if (!processingEnv.getTypeUtils().isAssignable(excType, params.get(1).asType())) {
143.1764 +                    error = true;
143.1765 +                }
143.1766 +            }
143.1767 +            if (error) {
143.1768 +                errElem = (ExecutableElement) e;
143.1769 +                err = "Error method first argument needs to be " + className + " and second Exception";
143.1770 +                continue;
143.1771 +            }
143.1772 +            return true;
143.1773 +        }
143.1774 +        if (err == null) {
143.1775 +            err = "Cannot find " + name + "(" + className + ", Exception) method in this class";
143.1776 +        }
143.1777 +        error(err, errElem);
143.1778 +        return false;
143.1779 +    }
143.1780 +    
143.1781 +}
   144.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   144.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/PropertyBindingAccessor.java	Tue Jan 07 08:21:57 2014 +0100
   144.3 @@ -0,0 +1,109 @@
   144.4 +/**
   144.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   144.6 + *
   144.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   144.8 + *
   144.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  144.10 + * Other names may be trademarks of their respective owners.
  144.11 + *
  144.12 + * The contents of this file are subject to the terms of either the GNU
  144.13 + * General Public License Version 2 only ("GPL") or the Common
  144.14 + * Development and Distribution License("CDDL") (collectively, the
  144.15 + * "License"). You may not use this file except in compliance with the
  144.16 + * License. You can obtain a copy of the License at
  144.17 + * http://www.netbeans.org/cddl-gplv2.html
  144.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  144.19 + * specific language governing permissions and limitations under the
  144.20 + * License.  When distributing the software, include this License Header
  144.21 + * Notice in each file and include the License file at
  144.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  144.23 + * particular file as subject to the "Classpath" exception as provided
  144.24 + * by Oracle in the GPL Version 2 section of the License file that
  144.25 + * accompanied this code. If applicable, add the following below the
  144.26 + * License Header, with the fields enclosed by brackets [] replaced by
  144.27 + * your own identifying information:
  144.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  144.29 + *
  144.30 + * Contributor(s):
  144.31 + *
  144.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  144.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  144.34 + *
  144.35 + * If you wish your version of this file to be governed by only the CDDL
  144.36 + * or only the GPL Version 2, indicate your decision by adding
  144.37 + * "[Contributor] elects to include this software in this distribution
  144.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  144.39 + * single choice of license, a recipient has the option to distribute
  144.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  144.41 + * to extend the choice of license to its licensees as provided above.
  144.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  144.43 + * Version 2 license, then the option applies only if the new code is
  144.44 + * made subject to such option by the copyright holder.
  144.45 + */
  144.46 +package org.netbeans.html.json.impl;
  144.47 +
  144.48 +import net.java.html.BrwsrCtx;
  144.49 +import org.apidesign.html.json.spi.FunctionBinding;
  144.50 +import org.apidesign.html.json.spi.JSONCall;
  144.51 +import org.apidesign.html.json.spi.PropertyBinding;
  144.52 +import org.apidesign.html.json.spi.Proto;
  144.53 +
  144.54 +/**
  144.55 + *
  144.56 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  144.57 + */
  144.58 +public abstract class PropertyBindingAccessor {
  144.59 +    private static PropertyBindingAccessor DEFAULT;
  144.60 +
  144.61 +    protected PropertyBindingAccessor() {
  144.62 +        if (DEFAULT != null) throw new IllegalStateException();
  144.63 +        DEFAULT = this;
  144.64 +    }
  144.65 +    
  144.66 +    static {
  144.67 +        JSON.initClass(PropertyBinding.class);
  144.68 +    }
  144.69 +
  144.70 +    protected abstract <M> PropertyBinding newBinding(
  144.71 +        Proto.Type<M> access, Bindings<?> bindings, String name, int index, M model, boolean readOnly
  144.72 +    );
  144.73 +    protected abstract JSONCall newCall(
  144.74 +        BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter,
  144.75 +        String method, Object data
  144.76 +    );
  144.77 +    
  144.78 +    protected abstract Bindings bindings(Proto proto, boolean initialize);
  144.79 +    protected abstract void notifyChange(Proto proto, int propIndex);
  144.80 +    protected abstract Proto findProto(Proto.Type<?> type, Object object);
  144.81 +    protected abstract <Model> Model cloneTo(Proto.Type<Model> type, Model model, BrwsrCtx c);
  144.82 +    protected abstract Object read(Proto.Type<?> from, BrwsrCtx c, Object data);
  144.83 +    
  144.84 +    static Bindings getBindings(Proto proto, boolean initialize) {
  144.85 +        return DEFAULT.bindings(proto, initialize);
  144.86 +    }
  144.87 +    
  144.88 +    static void notifyProtoChange(Proto proto, int propIndex) {
  144.89 +        DEFAULT.notifyChange(proto, propIndex);
  144.90 +    }
  144.91 +    
  144.92 +    static <M> PropertyBinding create(
  144.93 +        Proto.Type<M> access, Bindings<?> bindings, String name, int index, M model , boolean readOnly
  144.94 +    ) {
  144.95 +        return DEFAULT.newBinding(access, bindings, name, index, model, readOnly);
  144.96 +    }
  144.97 +    static JSONCall createCall(
  144.98 +        BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter, 
  144.99 +        String method, Object data
 144.100 +    ) {
 144.101 +        return DEFAULT.newCall(ctx, callback, urlBefore, urlAfter, method, data);
 144.102 +    }
 144.103 +    static Proto protoFor(Proto.Type<?> type, Object object) {
 144.104 +        return DEFAULT.findProto(type, object);
 144.105 +    }
 144.106 +    static <Model> Model clone(Proto.Type<Model> type, Model model, BrwsrCtx c) {
 144.107 +        return DEFAULT.cloneTo(type, model, c);
 144.108 +    }
 144.109 +    static Object readFrom(Proto.Type<?> from, BrwsrCtx c, Object data) {
 144.110 +        return DEFAULT.read(from, c, data);
 144.111 +    }
 144.112 +}
   145.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   145.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/RcvrJSON.java	Tue Jan 07 08:21:57 2014 +0100
   145.3 @@ -0,0 +1,128 @@
   145.4 +/**
   145.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   145.6 + *
   145.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   145.8 + *
   145.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  145.10 + * Other names may be trademarks of their respective owners.
  145.11 + *
  145.12 + * The contents of this file are subject to the terms of either the GNU
  145.13 + * General Public License Version 2 only ("GPL") or the Common
  145.14 + * Development and Distribution License("CDDL") (collectively, the
  145.15 + * "License"). You may not use this file except in compliance with the
  145.16 + * License. You can obtain a copy of the License at
  145.17 + * http://www.netbeans.org/cddl-gplv2.html
  145.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  145.19 + * specific language governing permissions and limitations under the
  145.20 + * License.  When distributing the software, include this License Header
  145.21 + * Notice in each file and include the License file at
  145.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  145.23 + * particular file as subject to the "Classpath" exception as provided
  145.24 + * by Oracle in the GPL Version 2 section of the License file that
  145.25 + * accompanied this code. If applicable, add the following below the
  145.26 + * License Header, with the fields enclosed by brackets [] replaced by
  145.27 + * your own identifying information:
  145.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  145.29 + *
  145.30 + * Contributor(s):
  145.31 + *
  145.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  145.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  145.34 + *
  145.35 + * If you wish your version of this file to be governed by only the CDDL
  145.36 + * or only the GPL Version 2, indicate your decision by adding
  145.37 + * "[Contributor] elects to include this software in this distribution
  145.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  145.39 + * single choice of license, a recipient has the option to distribute
  145.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  145.41 + * to extend the choice of license to its licensees as provided above.
  145.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  145.43 + * Version 2 license, then the option applies only if the new code is
  145.44 + * made subject to such option by the copyright holder.
  145.45 + */
  145.46 +package org.netbeans.html.json.impl;
  145.47 +
  145.48 +import java.util.ArrayList;
  145.49 +import net.java.html.BrwsrCtx;
  145.50 +
  145.51 +/** Super type for those who wish to receive JSON messages.
  145.52 + *
  145.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  145.54 + */
  145.55 +public abstract class RcvrJSON {
  145.56 +    protected void onOpen(MsgEvnt msg) {}
  145.57 +    protected abstract void onMessage(MsgEvnt msg);
  145.58 +    protected void onClose(MsgEvnt msg) {}
  145.59 +    protected abstract void onError(MsgEvnt msg);
  145.60 +    
  145.61 +    public abstract static class MsgEvnt {
  145.62 +        MsgEvnt() {
  145.63 +        }
  145.64 +        
  145.65 +        public Throwable getError() {
  145.66 +            return null;
  145.67 +        }
  145.68 +        
  145.69 +        public final Exception getException() {
  145.70 +            Throwable t = getError();
  145.71 +            if (t instanceof Exception) {
  145.72 +                return (Exception)t;
  145.73 +            }
  145.74 +            if (t == null) {
  145.75 +                return null;
  145.76 +            }
  145.77 +            return new Exception(t);
  145.78 +        }
  145.79 +        
  145.80 +        public Object[] getValues() {
  145.81 +            return null;
  145.82 +        }
  145.83 +        
  145.84 +        public abstract void dispatch(RcvrJSON r);
  145.85 +        
  145.86 +        public static MsgEvnt createError(final Throwable t) {
  145.87 +            return new MsgEvnt() {
  145.88 +                @Override
  145.89 +                public Throwable getError() {
  145.90 +                    return t;
  145.91 +                }
  145.92 +
  145.93 +                @Override
  145.94 +                public void dispatch(RcvrJSON r) {
  145.95 +                    r.onError(this);
  145.96 +                }
  145.97 +            };
  145.98 +        }
  145.99 +        
 145.100 +        public static MsgEvnt createMessage(final Object value) {
 145.101 +            return new MsgEvnt() {
 145.102 +                @Override
 145.103 +                public Object[] getValues() {
 145.104 +                    return value instanceof Object[] ? (Object[])value : new Object[] { value };
 145.105 +                }
 145.106 +                
 145.107 +                @Override
 145.108 +                public void dispatch(RcvrJSON r) {
 145.109 +                    r.onMessage(this);
 145.110 +                }
 145.111 +            };
 145.112 +        }
 145.113 +        
 145.114 +        public static MsgEvnt createOpen() {
 145.115 +            return new MsgEvnt() {
 145.116 +                @Override
 145.117 +                public void dispatch(RcvrJSON r) {
 145.118 +                    r.onOpen(this);
 145.119 +                }
 145.120 +            };
 145.121 +        }
 145.122 +
 145.123 +        public static MsgEvnt createClose() {
 145.124 +            return new MsgEvnt() {
 145.125 +                @Override
 145.126 +                public void dispatch(RcvrJSON r) {
 145.127 +                    r.onClose(this);
 145.128 +                }
 145.129 +            };
 145.130 +        }
 145.131 +    } }
   146.1 --- a/json/src/main/resources/org/apidesign/html/json/impl/Bundle.properties	Thu Dec 19 17:11:01 2013 +0100
   146.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   146.3 @@ -1,75 +0,0 @@
   146.4 -#
   146.5 -# HTML via Java(tm) Language Bindings
   146.6 -# Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   146.7 -#
   146.8 -# This program is free software: you can redistribute it and/or modify
   146.9 -# it under the terms of the GNU General Public License as published by
  146.10 -# the Free Software Foundation, version 2 of the License.
  146.11 -#
  146.12 -# This program is distributed in the hope that it will be useful,
  146.13 -# but WITHOUT ANY WARRANTY; without even the implied warranty of
  146.14 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  146.15 -# GNU General Public License for more details. apidesign.org
  146.16 -# designates this particular file as subject to the
  146.17 -# "Classpath" exception as provided by apidesign.org
  146.18 -# in the License file that accompanied this code.
  146.19 -#
  146.20 -# You should have received a copy of the GNU General Public License
  146.21 -# along with this program. Look for COPYING file in the top folder.
  146.22 -# If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  146.23 -#
  146.24 -
  146.25 -MSG_Completion_GET=The GET method means retrieve whatever information \
  146.26 - (in the form of an entity) is identified by the Request-URI. \
  146.27 - If the Request-URI refers to a data-producing process, \
  146.28 - it is the produced data which shall be returned as the entity in \
  146.29 - the response and not the source text of the process, \
  146.30 - unless that text happens to be the output of the process.
  146.31 -
  146.32 -MSG_Completion_HEAD=The HEAD method is identical to GET except that the server \
  146.33 - MUST NOT return a message-body in the response. The metainformation \
  146.34 - contained in the HTTP headers in response to a HEAD request SHOULD be \
  146.35 - identical to the information sent in response to a GET request. \
  146.36 - This method can be used for obtaining metainformation about the entity implied \
  146.37 - by the request without transferring the entity-body itself. \
  146.38 - This method is often used for testing hypertext links for validity, \
  146.39 - accessibility, and recent modification.
  146.40 -
  146.41 -MSG_Completion_POST=The POST method is used to request that the origin server \
  146.42 - accept the entity enclosed in the request as a new subordinate of the resource \
  146.43 - identified by the Request-URI in the Request-Line. POST is designed to allow \
  146.44 - a uniform method to cover annotation of existing resources,\ 
  146.45 - posting a message to a bulletin board, newsgroup, mailing list, or similar \
  146.46 - group of articles, providing a block of data, such as the result of submitting a \
  146.47 - form, to a data-handling process or extending a database through an append operation. \
  146.48 - The actual function performed by the POST method is determined by the server \
  146.49 - and is usually dependent on the Request-URI. The posted entity is subordinate \
  146.50 - to that URI in the same way that a file is subordinate to a directory containing it, \
  146.51 - a news article is subordinate to a newsgroup to which it is posted, \
  146.52 - or a record is subordinate to a database.
  146.53 -
  146.54 -MSG_Completion_PUT=The PUT method requests that the enclosed entity be stored \
  146.55 - under the supplied Request-URI. If the Request-URI refers to an already \
  146.56 - existing resource, the enclosed entity SHOULD be considered as a modified \
  146.57 - version of the one residing on the origin server. If the Request-URI does \
  146.58 - not point to an existing resource, and that URI is capable of being defined \
  146.59 - as a new resource by the requesting user agent, the origin server can \
  146.60 - create the resource with that URI. If a new resource is created, the origin \
  146.61 - server MUST inform the user agent via the 201 (Created) response. \
  146.62 - If an existing resource is modified, either the 200 (OK) or 204 (No Content) \
  146.63 - response codes SHOULD be sent to indicate successful completion of the request. \
  146.64 - If the resource could not be created or modified with the Request-URI, an \
  146.65 - appropriate error response SHOULD be given that reflects the nature of the problem. \
  146.66 - The recipient of the entity MUST NOT ignore any Content-* (e.g. Content-Range) \
  146.67 - headers that it does not understand or implement and MUST return \
  146.68 - a 501 (Not Implemented) response in such cases.
  146.69 -
  146.70 -MSG_Completion_DELETE=The DELETE method requests that the origin server delete \
  146.71 - the resource identified by the Request-URI. This method MAY be overridden \
  146.72 - by human intervention (or other means) on the origin server. The client \
  146.73 - cannot be guaranteed that the operation has been carried out, even if \
  146.74 - the status code returned from the origin server indicates that the action \
  146.75 - has been completed successfully. However, the server SHOULD NOT indicate \
  146.76 - success unless, at the time the response is given, it intends to delete \
  146.77 - the resource or move it to an inaccessible location.
  146.78 -
   147.1 --- a/json/src/main/resources/org/apidesign/html/json/spi/package.html	Thu Dec 19 17:11:01 2013 +0100
   147.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   147.3 @@ -1,37 +0,0 @@
   147.4 -<!--
   147.5 -
   147.6 -    HTML via Java(tm) Language Bindings
   147.7 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   147.8 -
   147.9 -    This program is free software: you can redistribute it and/or modify
  147.10 -    it under the terms of the GNU General Public License as published by
  147.11 -    the Free Software Foundation, version 2 of the License.
  147.12 -
  147.13 -    This program is distributed in the hope that it will be useful,
  147.14 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
  147.15 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  147.16 -    GNU General Public License for more details. apidesign.org
  147.17 -    designates this particular file as subject to the
  147.18 -    "Classpath" exception as provided by apidesign.org
  147.19 -    in the License file that accompanied this code.
  147.20 -
  147.21 -    You should have received a copy of the GNU General Public License
  147.22 -    along with this program. Look for COPYING file in the top folder.
  147.23 -    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  147.24 -
  147.25 --->
  147.26 -<!DOCTYPE html>
  147.27 -<html>
  147.28 -    <head>
  147.29 -        <title></title>
  147.30 -        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  147.31 -    </head>
  147.32 -    <body>
  147.33 -        <div>Implement 
  147.34 -            <a href="Technology.html">Technology</a> and
  147.35 -            <a href="Transfer.html">Transfer</a> and use 
  147.36 -            <a href="ContextBuilder.html">ContextBuilder</a> to create an instance
  147.37 -            of <code>Context</code> representing your technology.
  147.38 -        </div>
  147.39 -    </body>
  147.40 -</html>
   148.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   148.2 +++ b/json/src/main/resources/org/netbeans/html/json/impl/Bundle.properties	Tue Jan 07 08:21:57 2014 +0100
   148.3 @@ -0,0 +1,97 @@
   148.4 +#
   148.5 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   148.6 +#
   148.7 +# Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   148.8 +#
   148.9 +# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  148.10 +# Other names may be trademarks of their respective owners.
  148.11 +#
  148.12 +# The contents of this file are subject to the terms of either the GNU
  148.13 +# General Public License Version 2 only ("GPL") or the Common
  148.14 +# Development and Distribution License("CDDL") (collectively, the
  148.15 +# "License"). You may not use this file except in compliance with the
  148.16 +# License. You can obtain a copy of the License at
  148.17 +# http://www.netbeans.org/cddl-gplv2.html
  148.18 +# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  148.19 +# specific language governing permissions and limitations under the
  148.20 +# License.  When distributing the software, include this License Header
  148.21 +# Notice in each file and include the License file at
  148.22 +# nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  148.23 +# particular file as subject to the "Classpath" exception as provided
  148.24 +# by Oracle in the GPL Version 2 section of the License file that
  148.25 +# accompanied this code. If applicable, add the following below the
  148.26 +# License Header, with the fields enclosed by brackets [] replaced by
  148.27 +# your own identifying information:
  148.28 +# "Portions Copyrighted [year] [name of copyright owner]"
  148.29 +#
  148.30 +# Contributor(s):
  148.31 +#
  148.32 +# The Original Software is NetBeans. The Initial Developer of the Original
  148.33 +# Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  148.34 +#
  148.35 +# If you wish your version of this file to be governed by only the CDDL
  148.36 +# or only the GPL Version 2, indicate your decision by adding
  148.37 +# "[Contributor] elects to include this software in this distribution
  148.38 +# under the [CDDL or GPL Version 2] license." If you do not indicate a
  148.39 +# single choice of license, a recipient has the option to distribute
  148.40 +# your version of this file under either the CDDL, the GPL Version 2 or
  148.41 +# to extend the choice of license to its licensees as provided above.
  148.42 +# However, if you add GPL Version 2 code and therefore, elected the GPL
  148.43 +# Version 2 license, then the option applies only if the new code is
  148.44 +# made subject to such option by the copyright holder.
  148.45 +#
  148.46 +
  148.47 +MSG_Completion_GET=The GET method means retrieve whatever information \
  148.48 + (in the form of an entity) is identified by the Request-URI. \
  148.49 + If the Request-URI refers to a data-producing process, \
  148.50 + it is the produced data which shall be returned as the entity in \
  148.51 + the response and not the source text of the process, \
  148.52 + unless that text happens to be the output of the process.
  148.53 +
  148.54 +MSG_Completion_HEAD=The HEAD method is identical to GET except that the server \
  148.55 + MUST NOT return a message-body in the response. The metainformation \
  148.56 + contained in the HTTP headers in response to a HEAD request SHOULD be \
  148.57 + identical to the information sent in response to a GET request. \
  148.58 + This method can be used for obtaining metainformation about the entity implied \
  148.59 + by the request without transferring the entity-body itself. \
  148.60 + This method is often used for testing hypertext links for validity, \
  148.61 + accessibility, and recent modification.
  148.62 +
  148.63 +MSG_Completion_POST=The POST method is used to request that the origin server \
  148.64 + accept the entity enclosed in the request as a new subordinate of the resource \
  148.65 + identified by the Request-URI in the Request-Line. POST is designed to allow \
  148.66 + a uniform method to cover annotation of existing resources,\ 
  148.67 + posting a message to a bulletin board, newsgroup, mailing list, or similar \
  148.68 + group of articles, providing a block of data, such as the result of submitting a \
  148.69 + form, to a data-handling process or extending a database through an append operation. \
  148.70 + The actual function performed by the POST method is determined by the server \
  148.71 + and is usually dependent on the Request-URI. The posted entity is subordinate \
  148.72 + to that URI in the same way that a file is subordinate to a directory containing it, \
  148.73 + a news article is subordinate to a newsgroup to which it is posted, \
  148.74 + or a record is subordinate to a database.
  148.75 +
  148.76 +MSG_Completion_PUT=The PUT method requests that the enclosed entity be stored \
  148.77 + under the supplied Request-URI. If the Request-URI refers to an already \
  148.78 + existing resource, the enclosed entity SHOULD be considered as a modified \
  148.79 + version of the one residing on the origin server. If the Request-URI does \
  148.80 + not point to an existing resource, and that URI is capable of being defined \
  148.81 + as a new resource by the requesting user agent, the origin server can \
  148.82 + create the resource with that URI. If a new resource is created, the origin \
  148.83 + server MUST inform the user agent via the 201 (Created) response. \
  148.84 + If an existing resource is modified, either the 200 (OK) or 204 (No Content) \
  148.85 + response codes SHOULD be sent to indicate successful completion of the request. \
  148.86 + If the resource could not be created or modified with the Request-URI, an \
  148.87 + appropriate error response SHOULD be given that reflects the nature of the problem. \
  148.88 + The recipient of the entity MUST NOT ignore any Content-* (e.g. Content-Range) \
  148.89 + headers that it does not understand or implement and MUST return \
  148.90 + a 501 (Not Implemented) response in such cases.
  148.91 +
  148.92 +MSG_Completion_DELETE=The DELETE method requests that the origin server delete \
  148.93 + the resource identified by the Request-URI. This method MAY be overridden \
  148.94 + by human intervention (or other means) on the origin server. The client \
  148.95 + cannot be guaranteed that the operation has been carried out, even if \
  148.96 + the status code returned from the origin server indicates that the action \
  148.97 + has been completed successfully. However, the server SHOULD NOT indicate \
  148.98 + success unless, at the time the response is given, it intends to delete \
  148.99 + the resource or move it to an inaccessible location.
 148.100 +
   149.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   149.2 +++ b/json/src/main/resources/org/netbeans/html/json/spi/package.html	Tue Jan 07 08:21:57 2014 +0100
   149.3 @@ -0,0 +1,59 @@
   149.4 +<!--
   149.5 +
   149.6 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   149.7 +
   149.8 +    Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   149.9 +
  149.10 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  149.11 +    Other names may be trademarks of their respective owners.
  149.12 +
  149.13 +    The contents of this file are subject to the terms of either the GNU
  149.14 +    General Public License Version 2 only ("GPL") or the Common
  149.15 +    Development and Distribution License("CDDL") (collectively, the
  149.16 +    "License"). You may not use this file except in compliance with the
  149.17 +    License. You can obtain a copy of the License at
  149.18 +    http://www.netbeans.org/cddl-gplv2.html
  149.19 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  149.20 +    specific language governing permissions and limitations under the
  149.21 +    License.  When distributing the software, include this License Header
  149.22 +    Notice in each file and include the License file at
  149.23 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  149.24 +    particular file as subject to the "Classpath" exception as provided
  149.25 +    by Oracle in the GPL Version 2 section of the License file that
  149.26 +    accompanied this code. If applicable, add the following below the
  149.27 +    License Header, with the fields enclosed by brackets [] replaced by
  149.28 +    your own identifying information:
  149.29 +    "Portions Copyrighted [year] [name of copyright owner]"
  149.30 +
  149.31 +    Contributor(s):
  149.32 +
  149.33 +    The Original Software is NetBeans. The Initial Developer of the Original
  149.34 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  149.35 +
  149.36 +    If you wish your version of this file to be governed by only the CDDL
  149.37 +    or only the GPL Version 2, indicate your decision by adding
  149.38 +    "[Contributor] elects to include this software in this distribution
  149.39 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
  149.40 +    single choice of license, a recipient has the option to distribute
  149.41 +    your version of this file under either the CDDL, the GPL Version 2 or
  149.42 +    to extend the choice of license to its licensees as provided above.
  149.43 +    However, if you add GPL Version 2 code and therefore, elected the GPL
  149.44 +    Version 2 license, then the option applies only if the new code is
  149.45 +    made subject to such option by the copyright holder.
  149.46 +
  149.47 +-->
  149.48 +<!DOCTYPE html>
  149.49 +<html>
  149.50 +    <head>
  149.51 +        <title></title>
  149.52 +        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  149.53 +    </head>
  149.54 +    <body>
  149.55 +        <div>Implement 
  149.56 +            <a href="Technology.html">Technology</a> and
  149.57 +            <a href="Transfer.html">Transfer</a> and use 
  149.58 +            <a href="ContextBuilder.html">ContextBuilder</a> to create an instance
  149.59 +            of <code>Context</code> representing your technology.
  149.60 +        </div>
  149.61 +    </body>
  149.62 +</html>
   150.1 --- a/json/src/test/java/net/java/html/json/BoardTest.java	Thu Dec 19 17:11:01 2013 +0100
   150.2 +++ b/json/src/test/java/net/java/html/json/BoardTest.java	Tue Jan 07 08:21:57 2014 +0100
   150.3 @@ -1,22 +1,44 @@
   150.4  /**
   150.5 - * HTML via Java(tm) Language Bindings
   150.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   150.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   150.8   *
   150.9 - * This program is free software: you can redistribute it and/or modify
  150.10 - * it under the terms of the GNU General Public License as published by
  150.11 - * the Free Software Foundation, version 2 of the License.
  150.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  150.13   *
  150.14 - * This program is distributed in the hope that it will be useful,
  150.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  150.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  150.17 - * GNU General Public License for more details. apidesign.org
  150.18 - * designates this particular file as subject to the
  150.19 - * "Classpath" exception as provided by apidesign.org
  150.20 - * in the License file that accompanied this code.
  150.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  150.22 + * Other names may be trademarks of their respective owners.
  150.23   *
  150.24 - * You should have received a copy of the GNU General Public License
  150.25 - * along with this program. Look for COPYING file in the top folder.
  150.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  150.27 + * The contents of this file are subject to the terms of either the GNU
  150.28 + * General Public License Version 2 only ("GPL") or the Common
  150.29 + * Development and Distribution License("CDDL") (collectively, the
  150.30 + * "License"). You may not use this file except in compliance with the
  150.31 + * License. You can obtain a copy of the License at
  150.32 + * http://www.netbeans.org/cddl-gplv2.html
  150.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  150.34 + * specific language governing permissions and limitations under the
  150.35 + * License.  When distributing the software, include this License Header
  150.36 + * Notice in each file and include the License file at
  150.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  150.38 + * particular file as subject to the "Classpath" exception as provided
  150.39 + * by Oracle in the GPL Version 2 section of the License file that
  150.40 + * accompanied this code. If applicable, add the following below the
  150.41 + * License Header, with the fields enclosed by brackets [] replaced by
  150.42 + * your own identifying information:
  150.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  150.44 + *
  150.45 + * Contributor(s):
  150.46 + *
  150.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  150.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  150.49 + *
  150.50 + * If you wish your version of this file to be governed by only the CDDL
  150.51 + * or only the GPL Version 2, indicate your decision by adding
  150.52 + * "[Contributor] elects to include this software in this distribution
  150.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  150.54 + * single choice of license, a recipient has the option to distribute
  150.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  150.56 + * to extend the choice of license to its licensees as provided above.
  150.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  150.58 + * Version 2 license, then the option applies only if the new code is
  150.59 + * made subject to such option by the copyright holder.
  150.60   */
  150.61  package net.java.html.json;
  150.62  
   151.1 --- a/json/src/test/java/net/java/html/json/Compile.java	Thu Dec 19 17:11:01 2013 +0100
   151.2 +++ b/json/src/test/java/net/java/html/json/Compile.java	Tue Jan 07 08:21:57 2014 +0100
   151.3 @@ -1,22 +1,44 @@
   151.4  /**
   151.5 - * HTML via Java(tm) Language Bindings
   151.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   151.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   151.8   *
   151.9 - * This program is free software: you can redistribute it and/or modify
  151.10 - * it under the terms of the GNU General Public License as published by
  151.11 - * the Free Software Foundation, version 2 of the License.
  151.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  151.13   *
  151.14 - * This program is distributed in the hope that it will be useful,
  151.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  151.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  151.17 - * GNU General Public License for more details. apidesign.org
  151.18 - * designates this particular file as subject to the
  151.19 - * "Classpath" exception as provided by apidesign.org
  151.20 - * in the License file that accompanied this code.
  151.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  151.22 + * Other names may be trademarks of their respective owners.
  151.23   *
  151.24 - * You should have received a copy of the GNU General Public License
  151.25 - * along with this program. Look for COPYING file in the top folder.
  151.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  151.27 + * The contents of this file are subject to the terms of either the GNU
  151.28 + * General Public License Version 2 only ("GPL") or the Common
  151.29 + * Development and Distribution License("CDDL") (collectively, the
  151.30 + * "License"). You may not use this file except in compliance with the
  151.31 + * License. You can obtain a copy of the License at
  151.32 + * http://www.netbeans.org/cddl-gplv2.html
  151.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  151.34 + * specific language governing permissions and limitations under the
  151.35 + * License.  When distributing the software, include this License Header
  151.36 + * Notice in each file and include the License file at
  151.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  151.38 + * particular file as subject to the "Classpath" exception as provided
  151.39 + * by Oracle in the GPL Version 2 section of the License file that
  151.40 + * accompanied this code. If applicable, add the following below the
  151.41 + * License Header, with the fields enclosed by brackets [] replaced by
  151.42 + * your own identifying information:
  151.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  151.44 + *
  151.45 + * Contributor(s):
  151.46 + *
  151.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  151.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  151.49 + *
  151.50 + * If you wish your version of this file to be governed by only the CDDL
  151.51 + * or only the GPL Version 2, indicate your decision by adding
  151.52 + * "[Contributor] elects to include this software in this distribution
  151.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  151.54 + * single choice of license, a recipient has the option to distribute
  151.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  151.56 + * to extend the choice of license to its licensees as provided above.
  151.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  151.58 + * Version 2 license, then the option applies only if the new code is
  151.59 + * made subject to such option by the copyright holder.
  151.60   */
  151.61  package net.java.html.json;
  151.62  
   152.1 --- a/json/src/test/java/net/java/html/json/MapModelTest.java	Thu Dec 19 17:11:01 2013 +0100
   152.2 +++ b/json/src/test/java/net/java/html/json/MapModelTest.java	Tue Jan 07 08:21:57 2014 +0100
   152.3 @@ -1,22 +1,44 @@
   152.4  /**
   152.5 - * HTML via Java(tm) Language Bindings
   152.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   152.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   152.8   *
   152.9 - * This program is free software: you can redistribute it and/or modify
  152.10 - * it under the terms of the GNU General Public License as published by
  152.11 - * the Free Software Foundation, version 2 of the License.
  152.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  152.13   *
  152.14 - * This program is distributed in the hope that it will be useful,
  152.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  152.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  152.17 - * GNU General Public License for more details. apidesign.org
  152.18 - * designates this particular file as subject to the
  152.19 - * "Classpath" exception as provided by apidesign.org
  152.20 - * in the License file that accompanied this code.
  152.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  152.22 + * Other names may be trademarks of their respective owners.
  152.23   *
  152.24 - * You should have received a copy of the GNU General Public License
  152.25 - * along with this program. Look for COPYING file in the top folder.
  152.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  152.27 + * The contents of this file are subject to the terms of either the GNU
  152.28 + * General Public License Version 2 only ("GPL") or the Common
  152.29 + * Development and Distribution License("CDDL") (collectively, the
  152.30 + * "License"). You may not use this file except in compliance with the
  152.31 + * License. You can obtain a copy of the License at
  152.32 + * http://www.netbeans.org/cddl-gplv2.html
  152.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  152.34 + * specific language governing permissions and limitations under the
  152.35 + * License.  When distributing the software, include this License Header
  152.36 + * Notice in each file and include the License file at
  152.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  152.38 + * particular file as subject to the "Classpath" exception as provided
  152.39 + * by Oracle in the GPL Version 2 section of the License file that
  152.40 + * accompanied this code. If applicable, add the following below the
  152.41 + * License Header, with the fields enclosed by brackets [] replaced by
  152.42 + * your own identifying information:
  152.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  152.44 + *
  152.45 + * Contributor(s):
  152.46 + *
  152.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  152.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  152.49 + *
  152.50 + * If you wish your version of this file to be governed by only the CDDL
  152.51 + * or only the GPL Version 2, indicate your decision by adding
  152.52 + * "[Contributor] elects to include this software in this distribution
  152.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  152.54 + * single choice of license, a recipient has the option to distribute
  152.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  152.56 + * to extend the choice of license to its licensees as provided above.
  152.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  152.58 + * Version 2 license, then the option applies only if the new code is
  152.59 + * made subject to such option by the copyright holder.
  152.60   */
  152.61  package net.java.html.json;
  152.62  
  152.63 @@ -27,12 +49,12 @@
  152.64  import java.util.HashMap;
  152.65  import java.util.Map;
  152.66  import org.apidesign.html.context.spi.Contexts;
  152.67 -import org.apidesign.html.json.impl.WrapperObject;
  152.68  import org.apidesign.html.json.spi.FunctionBinding;
  152.69  import org.apidesign.html.json.spi.JSONCall;
  152.70  import org.apidesign.html.json.spi.PropertyBinding;
  152.71  import org.apidesign.html.json.spi.Technology;
  152.72  import org.apidesign.html.json.spi.Transfer;
  152.73 +import org.netbeans.html.json.impl.JSON;
  152.74  import org.testng.annotations.BeforeMethod;
  152.75  import org.testng.annotations.Test;
  152.76  import static org.testng.Assert.*;
  152.77 @@ -55,7 +77,7 @@
  152.78          Person p = Models.bind(new Person(), c).applyBindings();
  152.79          p.setFirstName("Jarda");
  152.80          
  152.81 -        Map m = (Map)WrapperObject.find(p);
  152.82 +        Map m = (Map)JSON.find(p);
  152.83          Object v = m.get("firstName");
  152.84          assertNotNull(v, "Value should be in the map");
  152.85          assertEquals(v.getClass(), One.class, "It is instance of One");
  152.86 @@ -76,7 +98,7 @@
  152.87          Person p = Models.bind(new Person(), c);
  152.88          p.setFirstName("Jirka");
  152.89          
  152.90 -        Map m = (Map)WrapperObject.find(p);
  152.91 +        Map m = (Map)JSON.find(p);
  152.92          Object v = m.get("firstName");
  152.93          assertNotNull(v, "Value should be in the map");
  152.94          assertEquals(v.getClass(), One.class, "It is instance of One");
  152.95 @@ -100,7 +122,7 @@
  152.96      @Test public void derivedProperty() throws Exception {
  152.97          Person p = Models.bind(new Person(), c);
  152.98          
  152.99 -        Map m = (Map)WrapperObject.find(p);
 152.100 +        Map m = (Map)JSON.find(p);
 152.101          Object v = m.get("fullName");
 152.102          assertNotNull(v, "Value should be in the map");
 152.103          assertEquals(v.getClass(), One.class, "It is instance of One");
 152.104 @@ -113,7 +135,7 @@
 152.105          p.setFirstName("Trans");
 152.106          p.setSex(Sex.MALE);
 152.107          
 152.108 -        Map m = (Map)WrapperObject.find(p);
 152.109 +        Map m = (Map)JSON.find(p);
 152.110          Object o = m.get("changeSex");
 152.111          assertNotNull(o, "Function registered in the model");
 152.112          assertEquals(o.getClass(), One.class);
 152.113 @@ -130,7 +152,7 @@
 152.114          Person p = Models.bind(new Person(), c);
 152.115          p.setFirstName("Trans");
 152.116          
 152.117 -        Map m = (Map)WrapperObject.find(p);
 152.118 +        Map m = (Map)JSON.find(p);
 152.119          Object o = m.get("changeSex");
 152.120          assertNotNull(o, "Function registered in the model");
 152.121          assertEquals(o.getClass(), One.class);
   153.1 --- a/json/src/test/java/net/java/html/json/ModelProcessorTest.java	Thu Dec 19 17:11:01 2013 +0100
   153.2 +++ b/json/src/test/java/net/java/html/json/ModelProcessorTest.java	Tue Jan 07 08:21:57 2014 +0100
   153.3 @@ -1,22 +1,44 @@
   153.4  /**
   153.5 - * HTML via Java(tm) Language Bindings
   153.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   153.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   153.8   *
   153.9 - * This program is free software: you can redistribute it and/or modify
  153.10 - * it under the terms of the GNU General Public License as published by
  153.11 - * the Free Software Foundation, version 2 of the License.
  153.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  153.13   *
  153.14 - * This program is distributed in the hope that it will be useful,
  153.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  153.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  153.17 - * GNU General Public License for more details. apidesign.org
  153.18 - * designates this particular file as subject to the
  153.19 - * "Classpath" exception as provided by apidesign.org
  153.20 - * in the License file that accompanied this code.
  153.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  153.22 + * Other names may be trademarks of their respective owners.
  153.23   *
  153.24 - * You should have received a copy of the GNU General Public License
  153.25 - * along with this program. Look for COPYING file in the top folder.
  153.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  153.27 + * The contents of this file are subject to the terms of either the GNU
  153.28 + * General Public License Version 2 only ("GPL") or the Common
  153.29 + * Development and Distribution License("CDDL") (collectively, the
  153.30 + * "License"). You may not use this file except in compliance with the
  153.31 + * License. You can obtain a copy of the License at
  153.32 + * http://www.netbeans.org/cddl-gplv2.html
  153.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  153.34 + * specific language governing permissions and limitations under the
  153.35 + * License.  When distributing the software, include this License Header
  153.36 + * Notice in each file and include the License file at
  153.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  153.38 + * particular file as subject to the "Classpath" exception as provided
  153.39 + * by Oracle in the GPL Version 2 section of the License file that
  153.40 + * accompanied this code. If applicable, add the following below the
  153.41 + * License Header, with the fields enclosed by brackets [] replaced by
  153.42 + * your own identifying information:
  153.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  153.44 + *
  153.45 + * Contributor(s):
  153.46 + *
  153.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  153.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  153.49 + *
  153.50 + * If you wish your version of this file to be governed by only the CDDL
  153.51 + * or only the GPL Version 2, indicate your decision by adding
  153.52 + * "[Contributor] elects to include this software in this distribution
  153.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  153.54 + * single choice of license, a recipient has the option to distribute
  153.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  153.56 + * to extend the choice of license to its licensees as provided above.
  153.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  153.58 + * Version 2 license, then the option applies only if the new code is
  153.59 + * made subject to such option by the copyright holder.
  153.60   */
  153.61  package net.java.html.json;
  153.62  
   154.1 --- a/json/src/test/java/net/java/html/json/ModelTest.java	Thu Dec 19 17:11:01 2013 +0100
   154.2 +++ b/json/src/test/java/net/java/html/json/ModelTest.java	Tue Jan 07 08:21:57 2014 +0100
   154.3 @@ -1,22 +1,44 @@
   154.4  /**
   154.5 - * HTML via Java(tm) Language Bindings
   154.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   154.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   154.8   *
   154.9 - * This program is free software: you can redistribute it and/or modify
  154.10 - * it under the terms of the GNU General Public License as published by
  154.11 - * the Free Software Foundation, version 2 of the License.
  154.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  154.13   *
  154.14 - * This program is distributed in the hope that it will be useful,
  154.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  154.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  154.17 - * GNU General Public License for more details. apidesign.org
  154.18 - * designates this particular file as subject to the
  154.19 - * "Classpath" exception as provided by apidesign.org
  154.20 - * in the License file that accompanied this code.
  154.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  154.22 + * Other names may be trademarks of their respective owners.
  154.23   *
  154.24 - * You should have received a copy of the GNU General Public License
  154.25 - * along with this program. Look for COPYING file in the top folder.
  154.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  154.27 + * The contents of this file are subject to the terms of either the GNU
  154.28 + * General Public License Version 2 only ("GPL") or the Common
  154.29 + * Development and Distribution License("CDDL") (collectively, the
  154.30 + * "License"). You may not use this file except in compliance with the
  154.31 + * License. You can obtain a copy of the License at
  154.32 + * http://www.netbeans.org/cddl-gplv2.html
  154.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  154.34 + * specific language governing permissions and limitations under the
  154.35 + * License.  When distributing the software, include this License Header
  154.36 + * Notice in each file and include the License file at
  154.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  154.38 + * particular file as subject to the "Classpath" exception as provided
  154.39 + * by Oracle in the GPL Version 2 section of the License file that
  154.40 + * accompanied this code. If applicable, add the following below the
  154.41 + * License Header, with the fields enclosed by brackets [] replaced by
  154.42 + * your own identifying information:
  154.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  154.44 + *
  154.45 + * Contributor(s):
  154.46 + *
  154.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  154.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  154.49 + *
  154.50 + * If you wish your version of this file to be governed by only the CDDL
  154.51 + * or only the GPL Version 2, indicate your decision by adding
  154.52 + * "[Contributor] elects to include this software in this distribution
  154.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  154.54 + * single choice of license, a recipient has the option to distribute
  154.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  154.56 + * to extend the choice of license to its licensees as provided above.
  154.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  154.58 + * Version 2 license, then the option applies only if the new code is
  154.59 + * made subject to such option by the copyright holder.
  154.60   */
  154.61  package net.java.html.json;
  154.62  
   155.1 --- a/json/src/test/java/net/java/html/json/ModelsTest.java	Thu Dec 19 17:11:01 2013 +0100
   155.2 +++ b/json/src/test/java/net/java/html/json/ModelsTest.java	Tue Jan 07 08:21:57 2014 +0100
   155.3 @@ -1,22 +1,44 @@
   155.4  /**
   155.5 - * HTML via Java(tm) Language Bindings
   155.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   155.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   155.8   *
   155.9 - * This program is free software: you can redistribute it and/or modify
  155.10 - * it under the terms of the GNU General Public License as published by
  155.11 - * the Free Software Foundation, version 2 of the License.
  155.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  155.13   *
  155.14 - * This program is distributed in the hope that it will be useful,
  155.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  155.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  155.17 - * GNU General Public License for more details. apidesign.org
  155.18 - * designates this particular file as subject to the
  155.19 - * "Classpath" exception as provided by apidesign.org
  155.20 - * in the License file that accompanied this code.
  155.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  155.22 + * Other names may be trademarks of their respective owners.
  155.23   *
  155.24 - * You should have received a copy of the GNU General Public License
  155.25 - * along with this program. Look for COPYING file in the top folder.
  155.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  155.27 + * The contents of this file are subject to the terms of either the GNU
  155.28 + * General Public License Version 2 only ("GPL") or the Common
  155.29 + * Development and Distribution License("CDDL") (collectively, the
  155.30 + * "License"). You may not use this file except in compliance with the
  155.31 + * License. You can obtain a copy of the License at
  155.32 + * http://www.netbeans.org/cddl-gplv2.html
  155.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  155.34 + * specific language governing permissions and limitations under the
  155.35 + * License.  When distributing the software, include this License Header
  155.36 + * Notice in each file and include the License file at
  155.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  155.38 + * particular file as subject to the "Classpath" exception as provided
  155.39 + * by Oracle in the GPL Version 2 section of the License file that
  155.40 + * accompanied this code. If applicable, add the following below the
  155.41 + * License Header, with the fields enclosed by brackets [] replaced by
  155.42 + * your own identifying information:
  155.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  155.44 + *
  155.45 + * Contributor(s):
  155.46 + *
  155.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  155.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  155.49 + *
  155.50 + * If you wish your version of this file to be governed by only the CDDL
  155.51 + * or only the GPL Version 2, indicate your decision by adding
  155.52 + * "[Contributor] elects to include this software in this distribution
  155.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  155.54 + * single choice of license, a recipient has the option to distribute
  155.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  155.56 + * to extend the choice of license to its licensees as provided above.
  155.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  155.58 + * Version 2 license, then the option applies only if the new code is
  155.59 + * made subject to such option by the copyright holder.
  155.60   */
  155.61  package net.java.html.json;
  155.62  
   156.1 --- a/json/src/test/java/net/java/html/json/OperationTest.java	Thu Dec 19 17:11:01 2013 +0100
   156.2 +++ b/json/src/test/java/net/java/html/json/OperationTest.java	Tue Jan 07 08:21:57 2014 +0100
   156.3 @@ -1,22 +1,44 @@
   156.4  /**
   156.5 - * HTML via Java(tm) Language Bindings
   156.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   156.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   156.8   *
   156.9 - * This program is free software: you can redistribute it and/or modify
  156.10 - * it under the terms of the GNU General Public License as published by
  156.11 - * the Free Software Foundation, version 2 of the License.
  156.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  156.13   *
  156.14 - * This program is distributed in the hope that it will be useful,
  156.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  156.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  156.17 - * GNU General Public License for more details. apidesign.org
  156.18 - * designates this particular file as subject to the
  156.19 - * "Classpath" exception as provided by apidesign.org
  156.20 - * in the License file that accompanied this code.
  156.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  156.22 + * Other names may be trademarks of their respective owners.
  156.23   *
  156.24 - * You should have received a copy of the GNU General Public License
  156.25 - * along with this program. Look for COPYING file in the top folder.
  156.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  156.27 + * The contents of this file are subject to the terms of either the GNU
  156.28 + * General Public License Version 2 only ("GPL") or the Common
  156.29 + * Development and Distribution License("CDDL") (collectively, the
  156.30 + * "License"). You may not use this file except in compliance with the
  156.31 + * License. You can obtain a copy of the License at
  156.32 + * http://www.netbeans.org/cddl-gplv2.html
  156.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  156.34 + * specific language governing permissions and limitations under the
  156.35 + * License.  When distributing the software, include this License Header
  156.36 + * Notice in each file and include the License file at
  156.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  156.38 + * particular file as subject to the "Classpath" exception as provided
  156.39 + * by Oracle in the GPL Version 2 section of the License file that
  156.40 + * accompanied this code. If applicable, add the following below the
  156.41 + * License Header, with the fields enclosed by brackets [] replaced by
  156.42 + * your own identifying information:
  156.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  156.44 + *
  156.45 + * Contributor(s):
  156.46 + *
  156.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  156.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  156.49 + *
  156.50 + * If you wish your version of this file to be governed by only the CDDL
  156.51 + * or only the GPL Version 2, indicate your decision by adding
  156.52 + * "[Contributor] elects to include this software in this distribution
  156.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  156.54 + * single choice of license, a recipient has the option to distribute
  156.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  156.56 + * to extend the choice of license to its licensees as provided above.
  156.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  156.58 + * Version 2 license, then the option applies only if the new code is
  156.59 + * made subject to such option by the copyright holder.
  156.60   */
  156.61  package net.java.html.json;
  156.62  
   157.1 --- a/json/src/test/java/net/java/html/json/PersonImpl.java	Thu Dec 19 17:11:01 2013 +0100
   157.2 +++ b/json/src/test/java/net/java/html/json/PersonImpl.java	Tue Jan 07 08:21:57 2014 +0100
   157.3 @@ -1,22 +1,44 @@
   157.4  /**
   157.5 - * HTML via Java(tm) Language Bindings
   157.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   157.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   157.8   *
   157.9 - * This program is free software: you can redistribute it and/or modify
  157.10 - * it under the terms of the GNU General Public License as published by
  157.11 - * the Free Software Foundation, version 2 of the License.
  157.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  157.13   *
  157.14 - * This program is distributed in the hope that it will be useful,
  157.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  157.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  157.17 - * GNU General Public License for more details. apidesign.org
  157.18 - * designates this particular file as subject to the
  157.19 - * "Classpath" exception as provided by apidesign.org
  157.20 - * in the License file that accompanied this code.
  157.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  157.22 + * Other names may be trademarks of their respective owners.
  157.23   *
  157.24 - * You should have received a copy of the GNU General Public License
  157.25 - * along with this program. Look for COPYING file in the top folder.
  157.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  157.27 + * The contents of this file are subject to the terms of either the GNU
  157.28 + * General Public License Version 2 only ("GPL") or the Common
  157.29 + * Development and Distribution License("CDDL") (collectively, the
  157.30 + * "License"). You may not use this file except in compliance with the
  157.31 + * License. You can obtain a copy of the License at
  157.32 + * http://www.netbeans.org/cddl-gplv2.html
  157.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  157.34 + * specific language governing permissions and limitations under the
  157.35 + * License.  When distributing the software, include this License Header
  157.36 + * Notice in each file and include the License file at
  157.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  157.38 + * particular file as subject to the "Classpath" exception as provided
  157.39 + * by Oracle in the GPL Version 2 section of the License file that
  157.40 + * accompanied this code. If applicable, add the following below the
  157.41 + * License Header, with the fields enclosed by brackets [] replaced by
  157.42 + * your own identifying information:
  157.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  157.44 + *
  157.45 + * Contributor(s):
  157.46 + *
  157.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  157.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  157.49 + *
  157.50 + * If you wish your version of this file to be governed by only the CDDL
  157.51 + * or only the GPL Version 2, indicate your decision by adding
  157.52 + * "[Contributor] elects to include this software in this distribution
  157.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  157.54 + * single choice of license, a recipient has the option to distribute
  157.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  157.56 + * to extend the choice of license to its licensees as provided above.
  157.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  157.58 + * Version 2 license, then the option applies only if the new code is
  157.59 + * made subject to such option by the copyright holder.
  157.60   */
  157.61  package net.java.html.json;
  157.62  
   158.1 --- a/json/src/test/java/net/java/html/json/PrimitiveArrayTest.java	Thu Dec 19 17:11:01 2013 +0100
   158.2 +++ b/json/src/test/java/net/java/html/json/PrimitiveArrayTest.java	Tue Jan 07 08:21:57 2014 +0100
   158.3 @@ -1,25 +1,48 @@
   158.4  /**
   158.5 - * HTML via Java(tm) Language Bindings
   158.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   158.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   158.8   *
   158.9 - * This program is free software: you can redistribute it and/or modify
  158.10 - * it under the terms of the GNU General Public License as published by
  158.11 - * the Free Software Foundation, version 2 of the License.
  158.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  158.13   *
  158.14 - * This program is distributed in the hope that it will be useful,
  158.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  158.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  158.17 - * GNU General Public License for more details. apidesign.org
  158.18 - * designates this particular file as subject to the
  158.19 - * "Classpath" exception as provided by apidesign.org
  158.20 - * in the License file that accompanied this code.
  158.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  158.22 + * Other names may be trademarks of their respective owners.
  158.23   *
  158.24 - * You should have received a copy of the GNU General Public License
  158.25 - * along with this program. Look for COPYING file in the top folder.
  158.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  158.27 + * The contents of this file are subject to the terms of either the GNU
  158.28 + * General Public License Version 2 only ("GPL") or the Common
  158.29 + * Development and Distribution License("CDDL") (collectively, the
  158.30 + * "License"). You may not use this file except in compliance with the
  158.31 + * License. You can obtain a copy of the License at
  158.32 + * http://www.netbeans.org/cddl-gplv2.html
  158.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  158.34 + * specific language governing permissions and limitations under the
  158.35 + * License.  When distributing the software, include this License Header
  158.36 + * Notice in each file and include the License file at
  158.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  158.38 + * particular file as subject to the "Classpath" exception as provided
  158.39 + * by Oracle in the GPL Version 2 section of the License file that
  158.40 + * accompanied this code. If applicable, add the following below the
  158.41 + * License Header, with the fields enclosed by brackets [] replaced by
  158.42 + * your own identifying information:
  158.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  158.44 + *
  158.45 + * Contributor(s):
  158.46 + *
  158.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  158.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  158.49 + *
  158.50 + * If you wish your version of this file to be governed by only the CDDL
  158.51 + * or only the GPL Version 2, indicate your decision by adding
  158.52 + * "[Contributor] elects to include this software in this distribution
  158.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  158.54 + * single choice of license, a recipient has the option to distribute
  158.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  158.56 + * to extend the choice of license to its licensees as provided above.
  158.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  158.58 + * Version 2 license, then the option applies only if the new code is
  158.59 + * made subject to such option by the copyright holder.
  158.60   */
  158.61  package net.java.html.json;
  158.62  
  158.63 +import java.util.List;
  158.64  import org.testng.Assert;
  158.65  import org.testng.annotations.Test;
  158.66  
  158.67 @@ -31,11 +54,16 @@
  158.68      @Property(name = "array", type = byte.class, array = true)
  158.69  })
  158.70  public class PrimitiveArrayTest {
  158.71 +    @ComputedProperty static int length(List<Byte> array) {
  158.72 +        return array.size();
  158.73 +    }
  158.74 +    
  158.75      @Test public void generatedConstructorWithPrimitiveType() {
  158.76          byte[] arr = new byte[10];
  158.77          arr[3] = 10;
  158.78          ByteArray a = new ByteArray(arr);
  158.79          Assert.assertEquals(a.getArray().size(), 10, "Ten elements");
  158.80          Assert.assertEquals(a.getArray().get(3).byteValue(), 10, "Value ten");
  158.81 +        Assert.assertEquals(a.getLength(), 10, "Derived property is OK too");
  158.82      }
  158.83  }
   159.1 --- a/json/src/test/java/net/java/html/json/Sex.java	Thu Dec 19 17:11:01 2013 +0100
   159.2 +++ b/json/src/test/java/net/java/html/json/Sex.java	Tue Jan 07 08:21:57 2014 +0100
   159.3 @@ -1,22 +1,44 @@
   159.4  /**
   159.5 - * HTML via Java(tm) Language Bindings
   159.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   159.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   159.8   *
   159.9 - * This program is free software: you can redistribute it and/or modify
  159.10 - * it under the terms of the GNU General Public License as published by
  159.11 - * the Free Software Foundation, version 2 of the License.
  159.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  159.13   *
  159.14 - * This program is distributed in the hope that it will be useful,
  159.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  159.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  159.17 - * GNU General Public License for more details. apidesign.org
  159.18 - * designates this particular file as subject to the
  159.19 - * "Classpath" exception as provided by apidesign.org
  159.20 - * in the License file that accompanied this code.
  159.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  159.22 + * Other names may be trademarks of their respective owners.
  159.23   *
  159.24 - * You should have received a copy of the GNU General Public License
  159.25 - * along with this program. Look for COPYING file in the top folder.
  159.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  159.27 + * The contents of this file are subject to the terms of either the GNU
  159.28 + * General Public License Version 2 only ("GPL") or the Common
  159.29 + * Development and Distribution License("CDDL") (collectively, the
  159.30 + * "License"). You may not use this file except in compliance with the
  159.31 + * License. You can obtain a copy of the License at
  159.32 + * http://www.netbeans.org/cddl-gplv2.html
  159.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  159.34 + * specific language governing permissions and limitations under the
  159.35 + * License.  When distributing the software, include this License Header
  159.36 + * Notice in each file and include the License file at
  159.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  159.38 + * particular file as subject to the "Classpath" exception as provided
  159.39 + * by Oracle in the GPL Version 2 section of the License file that
  159.40 + * accompanied this code. If applicable, add the following below the
  159.41 + * License Header, with the fields enclosed by brackets [] replaced by
  159.42 + * your own identifying information:
  159.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  159.44 + *
  159.45 + * Contributor(s):
  159.46 + *
  159.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  159.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  159.49 + *
  159.50 + * If you wish your version of this file to be governed by only the CDDL
  159.51 + * or only the GPL Version 2, indicate your decision by adding
  159.52 + * "[Contributor] elects to include this software in this distribution
  159.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  159.54 + * single choice of license, a recipient has the option to distribute
  159.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  159.56 + * to extend the choice of license to its licensees as provided above.
  159.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  159.58 + * Version 2 license, then the option applies only if the new code is
  159.59 + * made subject to such option by the copyright holder.
  159.60   */
  159.61  package net.java.html.json;
  159.62  
   160.1 --- a/json/src/test/java/net/java/html/json/TypesTest.java	Thu Dec 19 17:11:01 2013 +0100
   160.2 +++ b/json/src/test/java/net/java/html/json/TypesTest.java	Tue Jan 07 08:21:57 2014 +0100
   160.3 @@ -1,22 +1,44 @@
   160.4  /**
   160.5 - * HTML via Java(tm) Language Bindings
   160.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   160.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   160.8   *
   160.9 - * This program is free software: you can redistribute it and/or modify
  160.10 - * it under the terms of the GNU General Public License as published by
  160.11 - * the Free Software Foundation, version 2 of the License.
  160.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  160.13   *
  160.14 - * This program is distributed in the hope that it will be useful,
  160.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  160.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  160.17 - * GNU General Public License for more details. apidesign.org
  160.18 - * designates this particular file as subject to the
  160.19 - * "Classpath" exception as provided by apidesign.org
  160.20 - * in the License file that accompanied this code.
  160.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  160.22 + * Other names may be trademarks of their respective owners.
  160.23   *
  160.24 - * You should have received a copy of the GNU General Public License
  160.25 - * along with this program. Look for COPYING file in the top folder.
  160.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  160.27 + * The contents of this file are subject to the terms of either the GNU
  160.28 + * General Public License Version 2 only ("GPL") or the Common
  160.29 + * Development and Distribution License("CDDL") (collectively, the
  160.30 + * "License"). You may not use this file except in compliance with the
  160.31 + * License. You can obtain a copy of the License at
  160.32 + * http://www.netbeans.org/cddl-gplv2.html
  160.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  160.34 + * specific language governing permissions and limitations under the
  160.35 + * License.  When distributing the software, include this License Header
  160.36 + * Notice in each file and include the License file at
  160.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  160.38 + * particular file as subject to the "Classpath" exception as provided
  160.39 + * by Oracle in the GPL Version 2 section of the License file that
  160.40 + * accompanied this code. If applicable, add the following below the
  160.41 + * License Header, with the fields enclosed by brackets [] replaced by
  160.42 + * your own identifying information:
  160.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  160.44 + *
  160.45 + * Contributor(s):
  160.46 + *
  160.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  160.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  160.49 + *
  160.50 + * If you wish your version of this file to be governed by only the CDDL
  160.51 + * or only the GPL Version 2, indicate your decision by adding
  160.52 + * "[Contributor] elects to include this software in this distribution
  160.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  160.54 + * single choice of license, a recipient has the option to distribute
  160.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  160.56 + * to extend the choice of license to its licensees as provided above.
  160.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  160.58 + * Version 2 license, then the option applies only if the new code is
  160.59 + * made subject to such option by the copyright holder.
  160.60   */
  160.61  package net.java.html.json;
  160.62  
  160.63 @@ -24,9 +46,9 @@
  160.64  import java.util.Map;
  160.65  import net.java.html.json.MapModelTest.One;
  160.66  import org.apidesign.html.context.spi.Contexts;
  160.67 -import org.apidesign.html.json.impl.WrapperObject;
  160.68  import org.apidesign.html.json.spi.Technology;
  160.69  import org.apidesign.html.json.spi.Transfer;
  160.70 +import org.netbeans.html.json.impl.JSON;
  160.71  import org.testng.annotations.BeforeMethod;
  160.72  import org.testng.annotations.Test;
  160.73  import static org.testng.Assert.*;
  160.74 @@ -89,10 +111,10 @@
  160.75          t.setFloatX(99f);
  160.76          */
  160.77          
  160.78 -        Object json = WrapperObject.find(t);
  160.79 +        Object json = JSON.find(t);
  160.80          
  160.81          Types copy = Models.bind(new Types(), c);
  160.82 -        Map copyMap = (Map) WrapperObject.find(copy);
  160.83 +        Map copyMap = (Map) JSON.find(copy);
  160.84          One o = (One) copyMap.get("readFromEvent");
  160.85          o.fb.call(null, json);
  160.86          
   161.1 --- a/json/src/test/java/net/java/html/json/WebSocketCallTest.java	Thu Dec 19 17:11:01 2013 +0100
   161.2 +++ b/json/src/test/java/net/java/html/json/WebSocketCallTest.java	Tue Jan 07 08:21:57 2014 +0100
   161.3 @@ -1,22 +1,44 @@
   161.4  /**
   161.5 - * HTML via Java(tm) Language Bindings
   161.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   161.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   161.8   *
   161.9 - * This program is free software: you can redistribute it and/or modify
  161.10 - * it under the terms of the GNU General Public License as published by
  161.11 - * the Free Software Foundation, version 2 of the License.
  161.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  161.13   *
  161.14 - * This program is distributed in the hope that it will be useful,
  161.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  161.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  161.17 - * GNU General Public License for more details. apidesign.org
  161.18 - * designates this particular file as subject to the
  161.19 - * "Classpath" exception as provided by apidesign.org
  161.20 - * in the License file that accompanied this code.
  161.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  161.22 + * Other names may be trademarks of their respective owners.
  161.23   *
  161.24 - * You should have received a copy of the GNU General Public License
  161.25 - * along with this program. Look for COPYING file in the top folder.
  161.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  161.27 + * The contents of this file are subject to the terms of either the GNU
  161.28 + * General Public License Version 2 only ("GPL") or the Common
  161.29 + * Development and Distribution License("CDDL") (collectively, the
  161.30 + * "License"). You may not use this file except in compliance with the
  161.31 + * License. You can obtain a copy of the License at
  161.32 + * http://www.netbeans.org/cddl-gplv2.html
  161.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  161.34 + * specific language governing permissions and limitations under the
  161.35 + * License.  When distributing the software, include this License Header
  161.36 + * Notice in each file and include the License file at
  161.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  161.38 + * particular file as subject to the "Classpath" exception as provided
  161.39 + * by Oracle in the GPL Version 2 section of the License file that
  161.40 + * accompanied this code. If applicable, add the following below the
  161.41 + * License Header, with the fields enclosed by brackets [] replaced by
  161.42 + * your own identifying information:
  161.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  161.44 + *
  161.45 + * Contributor(s):
  161.46 + *
  161.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  161.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  161.49 + *
  161.50 + * If you wish your version of this file to be governed by only the CDDL
  161.51 + * or only the GPL Version 2, indicate your decision by adding
  161.52 + * "[Contributor] elects to include this software in this distribution
  161.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  161.54 + * single choice of license, a recipient has the option to distribute
  161.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  161.56 + * to extend the choice of license to its licensees as provided above.
  161.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  161.58 + * Version 2 license, then the option applies only if the new code is
  161.59 + * made subject to such option by the copyright holder.
  161.60   */
  161.61  package net.java.html.json;
  161.62  
   162.1 --- a/json/src/test/java/org/apidesign/html/json/impl/ConstructorTest.java	Thu Dec 19 17:11:01 2013 +0100
   162.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   162.3 @@ -1,58 +0,0 @@
   162.4 -/**
   162.5 - * HTML via Java(tm) Language Bindings
   162.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   162.7 - *
   162.8 - * This program is free software: you can redistribute it and/or modify
   162.9 - * it under the terms of the GNU General Public License as published by
  162.10 - * the Free Software Foundation, version 2 of the License.
  162.11 - *
  162.12 - * This program is distributed in the hope that it will be useful,
  162.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  162.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  162.15 - * GNU General Public License for more details. apidesign.org
  162.16 - * designates this particular file as subject to the
  162.17 - * "Classpath" exception as provided by apidesign.org
  162.18 - * in the License file that accompanied this code.
  162.19 - *
  162.20 - * You should have received a copy of the GNU General Public License
  162.21 - * along with this program. Look for COPYING file in the top folder.
  162.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  162.23 - */
  162.24 -package org.apidesign.html.json.impl;
  162.25 -
  162.26 -import net.java.html.json.Model;
  162.27 -import net.java.html.json.Property;
  162.28 -import static org.testng.Assert.assertNotNull;
  162.29 -import static org.testng.Assert.assertEquals;
  162.30 -import org.testng.annotations.Test;
  162.31 -
  162.32 -/**
  162.33 - *
  162.34 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  162.35 - */
  162.36 -@Model(className="Man", properties={
  162.37 -    @Property(name = "name", type = String.class),
  162.38 -    @Property(name = "other", type = Address.class, array = true),
  162.39 -    @Property(name = "primary", type = Address.class),
  162.40 -    @Property(name = "childrenNames", type = String.class, array = true)
  162.41 -})
  162.42 -public class ConstructorTest {
  162.43 -    @Model(className = "Address", properties = {
  162.44 -        @Property(name = "place", type = String.class)
  162.45 -    })
  162.46 -    static final class AddressModel {
  162.47 -    }
  162.48 -    
  162.49 -    @Test public void initializedByDefault() {
  162.50 -        Man m = new Man();
  162.51 -        assertNotNull(m.getPrimary(), "Single subobjects are initialized");
  162.52 -    }
  162.53 -    
  162.54 -    @Test public void hasRichConstructor() {
  162.55 -        Man m = new Man("Jarda", new Address("home"), new Address("work"), new Address("hotel"));
  162.56 -        assertEquals(m.getName(), "Jarda");
  162.57 -        assertNotNull(m.getPrimary(), "Primary address specified");
  162.58 -        assertNotNull(m.getPrimary().getPlace(), "home");
  162.59 -        assertEquals(m.getOther().size(), 2, "Two other addresses");
  162.60 -    }
  162.61 -}
   163.1 --- a/json/src/test/java/org/apidesign/html/json/impl/EmployeeImpl.java	Thu Dec 19 17:11:01 2013 +0100
   163.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   163.3 @@ -1,42 +0,0 @@
   163.4 -/**
   163.5 - * HTML via Java(tm) Language Bindings
   163.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   163.7 - *
   163.8 - * This program is free software: you can redistribute it and/or modify
   163.9 - * it under the terms of the GNU General Public License as published by
  163.10 - * the Free Software Foundation, version 2 of the License.
  163.11 - *
  163.12 - * This program is distributed in the hope that it will be useful,
  163.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  163.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  163.15 - * GNU General Public License for more details. apidesign.org
  163.16 - * designates this particular file as subject to the
  163.17 - * "Classpath" exception as provided by apidesign.org
  163.18 - * in the License file that accompanied this code.
  163.19 - *
  163.20 - * You should have received a copy of the GNU General Public License
  163.21 - * along with this program. Look for COPYING file in the top folder.
  163.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  163.23 - */
  163.24 -
  163.25 -package org.apidesign.html.json.impl;
  163.26 -
  163.27 -import net.java.html.json.Model;
  163.28 -import net.java.html.json.OnReceive;
  163.29 -import net.java.html.json.Person;
  163.30 -import net.java.html.json.Property;
  163.31 -
  163.32 -/**
  163.33 - *
  163.34 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  163.35 - */
  163.36 -@Model(className = "Employee", properties = {
  163.37 -    @Property(name = "person", type = Person.class),
  163.38 -    @Property(name = "employer", type = Employer.class)
  163.39 -})
  163.40 -public class EmployeeImpl {
  163.41 -    @OnReceive(url = "some/url")
  163.42 -    static void changePersonality(Employee e, Person p) {
  163.43 -        e.setPerson(p);
  163.44 -    }
  163.45 -}
   164.1 --- a/json/src/test/java/org/apidesign/html/json/impl/EmployerTest.java	Thu Dec 19 17:11:01 2013 +0100
   164.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   164.3 @@ -1,43 +0,0 @@
   164.4 -/**
   164.5 - * HTML via Java(tm) Language Bindings
   164.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   164.7 - *
   164.8 - * This program is free software: you can redistribute it and/or modify
   164.9 - * it under the terms of the GNU General Public License as published by
  164.10 - * the Free Software Foundation, version 2 of the License.
  164.11 - *
  164.12 - * This program is distributed in the hope that it will be useful,
  164.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  164.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  164.15 - * GNU General Public License for more details. apidesign.org
  164.16 - * designates this particular file as subject to the
  164.17 - * "Classpath" exception as provided by apidesign.org
  164.18 - * in the License file that accompanied this code.
  164.19 - *
  164.20 - * You should have received a copy of the GNU General Public License
  164.21 - * along with this program. Look for COPYING file in the top folder.
  164.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  164.23 - */
  164.24 -package org.apidesign.html.json.impl;
  164.25 -
  164.26 -import net.java.html.BrwsrCtx;
  164.27 -import net.java.html.json.Model;
  164.28 -import net.java.html.json.Models;
  164.29 -import net.java.html.json.Property;
  164.30 -import org.testng.Assert;
  164.31 -import org.testng.annotations.Test;
  164.32 -
  164.33 -/**
  164.34 - *
  164.35 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  164.36 - */
  164.37 -@Model(className = "Employer", properties = {
  164.38 -    @Property(name = "name", type = String.class)
  164.39 -})
  164.40 -public class EmployerTest {
  164.41 -    @Test public void preLoadsTheClass() {
  164.42 -        Employer em = Models.fromRaw(BrwsrCtx.EMPTY, Employer.class, this);
  164.43 -        Assert.assertNotNull(em, "Class loaded");
  164.44 -        em.applyBindings();
  164.45 -    }
  164.46 -}
   165.1 --- a/json/src/test/java/org/apidesign/html/json/impl/JSONListTest.java	Thu Dec 19 17:11:01 2013 +0100
   165.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   165.3 @@ -1,170 +0,0 @@
   165.4 -/**
   165.5 - * HTML via Java(tm) Language Bindings
   165.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   165.7 - *
   165.8 - * This program is free software: you can redistribute it and/or modify
   165.9 - * it under the terms of the GNU General Public License as published by
  165.10 - * the Free Software Foundation, version 2 of the License.
  165.11 - *
  165.12 - * This program is distributed in the hope that it will be useful,
  165.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  165.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  165.15 - * GNU General Public License for more details. apidesign.org
  165.16 - * designates this particular file as subject to the
  165.17 - * "Classpath" exception as provided by apidesign.org
  165.18 - * in the License file that accompanied this code.
  165.19 - *
  165.20 - * You should have received a copy of the GNU General Public License
  165.21 - * along with this program. Look for COPYING file in the top folder.
  165.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  165.23 - */
  165.24 -package org.apidesign.html.json.impl;
  165.25 -
  165.26 -import java.util.HashMap;
  165.27 -import java.util.Map;
  165.28 -import net.java.html.BrwsrCtx;
  165.29 -import net.java.html.json.Models;
  165.30 -import net.java.html.json.People;
  165.31 -import net.java.html.json.Person;
  165.32 -import net.java.html.json.Sex;
  165.33 -import org.apidesign.html.context.spi.Contexts;
  165.34 -import org.apidesign.html.json.spi.FunctionBinding;
  165.35 -import org.apidesign.html.json.spi.PropertyBinding;
  165.36 -import org.apidesign.html.json.spi.Technology;
  165.37 -import static org.testng.Assert.*;
  165.38 -import org.testng.annotations.BeforeMethod;
  165.39 -import org.testng.annotations.Test;
  165.40 -
  165.41 -/**
  165.42 - *
  165.43 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  165.44 - */
  165.45 -public class JSONListTest implements Technology<Object> {
  165.46 -    private boolean replaceArray;
  165.47 -    private final Map<String,PropertyBinding> bindings = new HashMap<String,PropertyBinding>();
  165.48 -    
  165.49 -    public JSONListTest() {
  165.50 -    }
  165.51 -    
  165.52 -    @BeforeMethod public void clear() {
  165.53 -        replaceArray = false;
  165.54 -    }
  165.55 -
  165.56 -    @Test public void testConvertorOnAnObject() {
  165.57 -        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
  165.58 -        
  165.59 -        Person p = Models.bind(new Person(), c);
  165.60 -        p.setFirstName("1");
  165.61 -        p.setLastName("2");
  165.62 -        p.setSex(Sex.MALE);
  165.63 -
  165.64 -        Object real = WrapperObject.find(p);
  165.65 -        assertEquals(this, real, "I am the right model");
  165.66 -    }
  165.67 -    
  165.68 -    @Test public void testConvertorOnAnArray() {
  165.69 -        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
  165.70 -        
  165.71 -        Person p = Models.bind(new Person(), c);
  165.72 -        p.setFirstName("1");
  165.73 -        p.setLastName("2");
  165.74 -        p.setSex(Sex.MALE);
  165.75 -        
  165.76 -        People people = Models.bind(new People(p), c).applyBindings();
  165.77 -        assertEquals(people.getInfo().toString(), "[{\"firstName\":\"1\",\"lastName\":\"2\",\"sex\":\"MALE\"}]", "Converted to real JSON");
  165.78 -        
  165.79 -        PropertyBinding pb = bindings.get("info");
  165.80 -        assertNotNull(pb, "Binding for info found");
  165.81 -        
  165.82 -        Object real = pb.getValue();
  165.83 -        assertTrue(real instanceof Object[], "It is an array: " + real);
  165.84 -        Object[] arr = (Object[])real;
  165.85 -        assertEquals(arr.length, 1, "Size is one");
  165.86 -        assertEquals(this, arr[0], "I am the right model");
  165.87 -    }
  165.88 -    
  165.89 -    @Test public void testNicknames() {
  165.90 -        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
  165.91 -        
  165.92 -        People people = Models.bind(new People(), c).applyBindings();
  165.93 -        people.getNicknames().add("One");
  165.94 -        people.getNicknames().add("Two");
  165.95 -        
  165.96 -        PropertyBinding pb = bindings.get("nicknames");
  165.97 -        assertNotNull(pb, "Binding for info found");
  165.98 -        
  165.99 -        Object real = pb.getValue();
 165.100 -        assertTrue(real instanceof Object[], "It is an array: " + real);
 165.101 -        Object[] arr = (Object[])real;
 165.102 -        assertEquals(arr.length, 2, "Length two");
 165.103 -        assertEquals(arr[0], "One", "Text should be in the model");
 165.104 -        assertEquals(arr[1], "Two", "2nd text in the model");
 165.105 -    }
 165.106 -    
 165.107 -    @Test public void testConvertorOnAnArrayWithWrapper() {
 165.108 -        this.replaceArray = true;
 165.109 -        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
 165.110 -        
 165.111 -        Person p = Models.bind(new Person(), c);
 165.112 -        p.setFirstName("1");
 165.113 -        p.setLastName("2");
 165.114 -        p.setSex(Sex.MALE);
 165.115 -        
 165.116 -        People people = Models.bind(new People(), c).applyBindings();
 165.117 -        people.getInfo().add(p);
 165.118 -        
 165.119 -        Object real = WrapperObject.find(people.getInfo());
 165.120 -        assertEquals(real, this, "I am the model of the array");
 165.121 -    }
 165.122 -
 165.123 -    @Test public void bindingsOnArray() {
 165.124 -        this.replaceArray = true;
 165.125 -        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
 165.126 -        
 165.127 -        People p = Models.bind(new People(), c).applyBindings();
 165.128 -        p.getAge().add(30);
 165.129 -        
 165.130 -        PropertyBinding pb = bindings.get("age");
 165.131 -        assertNotNull(pb, "There is a binding for age list");
 165.132 -        
 165.133 -        assertEquals(pb.getValue(), this, "I am the model of the array");
 165.134 -    }
 165.135 -
 165.136 -    @Override
 165.137 -    public Object wrapModel(Object model) {
 165.138 -        return this;
 165.139 -    }
 165.140 -
 165.141 -    @Override
 165.142 -    public void bind(PropertyBinding b, Object model, Object data) {
 165.143 -        bindings.put(b.getPropertyName(), b);
 165.144 -    }
 165.145 -
 165.146 -    @Override
 165.147 -    public void valueHasMutated(Object data, String propertyName) {
 165.148 -    }
 165.149 -
 165.150 -    @Override
 165.151 -    public void expose(FunctionBinding fb, Object model, Object d) {
 165.152 -    }
 165.153 -
 165.154 -    @Override
 165.155 -    public void applyBindings(Object data) {
 165.156 -    }
 165.157 -
 165.158 -    @Override
 165.159 -    public Object wrapArray(Object[] arr) {
 165.160 -        return replaceArray ? this : arr;
 165.161 -    }
 165.162 -
 165.163 -    @Override
 165.164 -    public <M> M toModel(Class<M> modelClass, Object data) {
 165.165 -        return modelClass.cast(data);
 165.166 -    }
 165.167 -
 165.168 -    @Override
 165.169 -    public void runSafe(Runnable r) {
 165.170 -        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
 165.171 -    }
 165.172 -
 165.173 -}
   166.1 --- a/json/src/test/java/org/apidesign/html/json/impl/JSONTest.java	Thu Dec 19 17:11:01 2013 +0100
   166.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   166.3 @@ -1,62 +0,0 @@
   166.4 -/**
   166.5 - * HTML via Java(tm) Language Bindings
   166.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   166.7 - *
   166.8 - * This program is free software: you can redistribute it and/or modify
   166.9 - * it under the terms of the GNU General Public License as published by
  166.10 - * the Free Software Foundation, version 2 of the License.
  166.11 - *
  166.12 - * This program is distributed in the hope that it will be useful,
  166.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  166.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  166.15 - * GNU General Public License for more details. apidesign.org
  166.16 - * designates this particular file as subject to the
  166.17 - * "Classpath" exception as provided by apidesign.org
  166.18 - * in the License file that accompanied this code.
  166.19 - *
  166.20 - * You should have received a copy of the GNU General Public License
  166.21 - * along with this program. Look for COPYING file in the top folder.
  166.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  166.23 - */
  166.24 -package org.apidesign.html.json.impl;
  166.25 -
  166.26 -import static org.testng.Assert.*;
  166.27 -import org.testng.annotations.Test;
  166.28 -
  166.29 -/**
  166.30 - *
  166.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  166.32 - */
  166.33 -public class JSONTest {
  166.34 -    
  166.35 -    public JSONTest() {
  166.36 -    }
  166.37 -
  166.38 -    @Test public void longToStringValue() {
  166.39 -        assertEquals(JSON.stringValue(Long.valueOf(1)), "1");
  166.40 -    }
  166.41 -    
  166.42 -    @Test public void booleanIsSortOfNumber() {
  166.43 -        assertEquals(JSON.numberValue(Boolean.TRUE), Integer.valueOf(1));
  166.44 -        assertEquals(JSON.numberValue(Boolean.FALSE), Integer.valueOf(0));
  166.45 -    }
  166.46 -    
  166.47 -    @Test public void numberToChar() {
  166.48 -        assertEquals(JSON.charValue(65), Character.valueOf('A'));
  166.49 -    }
  166.50 -    @Test public void booleanToChar() {
  166.51 -        assertEquals(JSON.charValue(false), Character.valueOf((char)0));
  166.52 -        assertEquals(JSON.charValue(true), Character.valueOf((char)1));
  166.53 -    }
  166.54 -    @Test public void stringToChar() {
  166.55 -        assertEquals(JSON.charValue("Ahoj"), Character.valueOf('A'));
  166.56 -    }
  166.57 -    @Test public void stringToBoolean() {
  166.58 -        assertEquals(JSON.boolValue("false"), Boolean.FALSE);
  166.59 -        assertEquals(JSON.boolValue("True"), Boolean.TRUE);
  166.60 -    }
  166.61 -    @Test public void numberToBoolean() {
  166.62 -        assertEquals(JSON.boolValue(0), Boolean.FALSE);
  166.63 -        assertEquals(JSON.boolValue(1), Boolean.TRUE);
  166.64 -    }
  166.65 -}
   167.1 --- a/json/src/test/java/org/apidesign/html/json/impl/NoPropertiesTest.java	Thu Dec 19 17:11:01 2013 +0100
   167.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   167.3 @@ -1,33 +0,0 @@
   167.4 -/**
   167.5 - * HTML via Java(tm) Language Bindings
   167.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   167.7 - *
   167.8 - * This program is free software: you can redistribute it and/or modify
   167.9 - * it under the terms of the GNU General Public License as published by
  167.10 - * the Free Software Foundation, version 2 of the License.
  167.11 - *
  167.12 - * This program is distributed in the hope that it will be useful,
  167.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  167.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  167.15 - * GNU General Public License for more details. apidesign.org
  167.16 - * designates this particular file as subject to the
  167.17 - * "Classpath" exception as provided by apidesign.org
  167.18 - * in the License file that accompanied this code.
  167.19 - *
  167.20 - * You should have received a copy of the GNU General Public License
  167.21 - * along with this program. Look for COPYING file in the top folder.
  167.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  167.23 - */
  167.24 -package org.apidesign.html.json.impl;
  167.25 -
  167.26 -import net.java.html.json.Model;
  167.27 -
  167.28 -/** Originally could not compile.
  167.29 - *
  167.30 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  167.31 - */
  167.32 -@Model(className="NoProperties", properties = {
  167.33 -})
  167.34 -public class NoPropertiesTest {
  167.35 -    
  167.36 -}
   168.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   168.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/ConstructorTest.java	Tue Jan 07 08:21:57 2014 +0100
   168.3 @@ -0,0 +1,80 @@
   168.4 +/**
   168.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   168.6 + *
   168.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   168.8 + *
   168.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  168.10 + * Other names may be trademarks of their respective owners.
  168.11 + *
  168.12 + * The contents of this file are subject to the terms of either the GNU
  168.13 + * General Public License Version 2 only ("GPL") or the Common
  168.14 + * Development and Distribution License("CDDL") (collectively, the
  168.15 + * "License"). You may not use this file except in compliance with the
  168.16 + * License. You can obtain a copy of the License at
  168.17 + * http://www.netbeans.org/cddl-gplv2.html
  168.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  168.19 + * specific language governing permissions and limitations under the
  168.20 + * License.  When distributing the software, include this License Header
  168.21 + * Notice in each file and include the License file at
  168.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  168.23 + * particular file as subject to the "Classpath" exception as provided
  168.24 + * by Oracle in the GPL Version 2 section of the License file that
  168.25 + * accompanied this code. If applicable, add the following below the
  168.26 + * License Header, with the fields enclosed by brackets [] replaced by
  168.27 + * your own identifying information:
  168.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  168.29 + *
  168.30 + * Contributor(s):
  168.31 + *
  168.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  168.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  168.34 + *
  168.35 + * If you wish your version of this file to be governed by only the CDDL
  168.36 + * or only the GPL Version 2, indicate your decision by adding
  168.37 + * "[Contributor] elects to include this software in this distribution
  168.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  168.39 + * single choice of license, a recipient has the option to distribute
  168.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  168.41 + * to extend the choice of license to its licensees as provided above.
  168.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  168.43 + * Version 2 license, then the option applies only if the new code is
  168.44 + * made subject to such option by the copyright holder.
  168.45 + */
  168.46 +package org.netbeans.html.json.impl;
  168.47 +
  168.48 +import net.java.html.json.Model;
  168.49 +import net.java.html.json.Property;
  168.50 +import static org.testng.Assert.assertNotNull;
  168.51 +import static org.testng.Assert.assertEquals;
  168.52 +import org.testng.annotations.Test;
  168.53 +
  168.54 +/**
  168.55 + *
  168.56 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  168.57 + */
  168.58 +@Model(className="Man", properties={
  168.59 +    @Property(name = "name", type = String.class),
  168.60 +    @Property(name = "other", type = Address.class, array = true),
  168.61 +    @Property(name = "primary", type = Address.class),
  168.62 +    @Property(name = "childrenNames", type = String.class, array = true)
  168.63 +})
  168.64 +public class ConstructorTest {
  168.65 +    @Model(className = "Address", properties = {
  168.66 +        @Property(name = "place", type = String.class)
  168.67 +    })
  168.68 +    static final class AddressModel {
  168.69 +    }
  168.70 +    
  168.71 +    @Test public void initializedByDefault() {
  168.72 +        Man m = new Man();
  168.73 +        assertNotNull(m.getPrimary(), "Single subobjects are initialized");
  168.74 +    }
  168.75 +    
  168.76 +    @Test public void hasRichConstructor() {
  168.77 +        Man m = new Man("Jarda", new Address("home"), new Address("work"), new Address("hotel"));
  168.78 +        assertEquals(m.getName(), "Jarda");
  168.79 +        assertNotNull(m.getPrimary(), "Primary address specified");
  168.80 +        assertNotNull(m.getPrimary().getPlace(), "home");
  168.81 +        assertEquals(m.getOther().size(), 2, "Two other addresses");
  168.82 +    }
  168.83 +}
   169.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   169.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/EmployeeImpl.java	Tue Jan 07 08:21:57 2014 +0100
   169.3 @@ -0,0 +1,63 @@
   169.4 +/**
   169.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   169.6 + *
   169.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   169.8 + *
   169.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  169.10 + * Other names may be trademarks of their respective owners.
  169.11 + *
  169.12 + * The contents of this file are subject to the terms of either the GNU
  169.13 + * General Public License Version 2 only ("GPL") or the Common
  169.14 + * Development and Distribution License("CDDL") (collectively, the
  169.15 + * "License"). You may not use this file except in compliance with the
  169.16 + * License. You can obtain a copy of the License at
  169.17 + * http://www.netbeans.org/cddl-gplv2.html
  169.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  169.19 + * specific language governing permissions and limitations under the
  169.20 + * License.  When distributing the software, include this License Header
  169.21 + * Notice in each file and include the License file at
  169.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  169.23 + * particular file as subject to the "Classpath" exception as provided
  169.24 + * by Oracle in the GPL Version 2 section of the License file that
  169.25 + * accompanied this code. If applicable, add the following below the
  169.26 + * License Header, with the fields enclosed by brackets [] replaced by
  169.27 + * your own identifying information:
  169.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  169.29 + *
  169.30 + * Contributor(s):
  169.31 + *
  169.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  169.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  169.34 + *
  169.35 + * If you wish your version of this file to be governed by only the CDDL
  169.36 + * or only the GPL Version 2, indicate your decision by adding
  169.37 + * "[Contributor] elects to include this software in this distribution
  169.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  169.39 + * single choice of license, a recipient has the option to distribute
  169.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  169.41 + * to extend the choice of license to its licensees as provided above.
  169.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  169.43 + * Version 2 license, then the option applies only if the new code is
  169.44 + * made subject to such option by the copyright holder.
  169.45 + */
  169.46 +package org.netbeans.html.json.impl;
  169.47 +
  169.48 +import net.java.html.json.Model;
  169.49 +import net.java.html.json.OnReceive;
  169.50 +import net.java.html.json.Person;
  169.51 +import net.java.html.json.Property;
  169.52 +
  169.53 +/**
  169.54 + *
  169.55 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  169.56 + */
  169.57 +@Model(className = "Employee", properties = {
  169.58 +    @Property(name = "person", type = Person.class),
  169.59 +    @Property(name = "employer", type = Employer.class)
  169.60 +})
  169.61 +public class EmployeeImpl {
  169.62 +    @OnReceive(url = "some/url")
  169.63 +    static void changePersonality(Employee e, Person p) {
  169.64 +        e.setPerson(p);
  169.65 +    }
  169.66 +}
   170.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   170.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/EmployerTest.java	Tue Jan 07 08:21:57 2014 +0100
   170.3 @@ -0,0 +1,65 @@
   170.4 +/**
   170.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   170.6 + *
   170.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   170.8 + *
   170.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  170.10 + * Other names may be trademarks of their respective owners.
  170.11 + *
  170.12 + * The contents of this file are subject to the terms of either the GNU
  170.13 + * General Public License Version 2 only ("GPL") or the Common
  170.14 + * Development and Distribution License("CDDL") (collectively, the
  170.15 + * "License"). You may not use this file except in compliance with the
  170.16 + * License. You can obtain a copy of the License at
  170.17 + * http://www.netbeans.org/cddl-gplv2.html
  170.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  170.19 + * specific language governing permissions and limitations under the
  170.20 + * License.  When distributing the software, include this License Header
  170.21 + * Notice in each file and include the License file at
  170.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  170.23 + * particular file as subject to the "Classpath" exception as provided
  170.24 + * by Oracle in the GPL Version 2 section of the License file that
  170.25 + * accompanied this code. If applicable, add the following below the
  170.26 + * License Header, with the fields enclosed by brackets [] replaced by
  170.27 + * your own identifying information:
  170.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  170.29 + *
  170.30 + * Contributor(s):
  170.31 + *
  170.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  170.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  170.34 + *
  170.35 + * If you wish your version of this file to be governed by only the CDDL
  170.36 + * or only the GPL Version 2, indicate your decision by adding
  170.37 + * "[Contributor] elects to include this software in this distribution
  170.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  170.39 + * single choice of license, a recipient has the option to distribute
  170.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  170.41 + * to extend the choice of license to its licensees as provided above.
  170.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  170.43 + * Version 2 license, then the option applies only if the new code is
  170.44 + * made subject to such option by the copyright holder.
  170.45 + */
  170.46 +package org.netbeans.html.json.impl;
  170.47 +
  170.48 +import net.java.html.BrwsrCtx;
  170.49 +import net.java.html.json.Model;
  170.50 +import net.java.html.json.Models;
  170.51 +import net.java.html.json.Property;
  170.52 +import org.testng.Assert;
  170.53 +import org.testng.annotations.Test;
  170.54 +
  170.55 +/**
  170.56 + *
  170.57 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  170.58 + */
  170.59 +@Model(className = "Employer", properties = {
  170.60 +    @Property(name = "name", type = String.class)
  170.61 +})
  170.62 +public class EmployerTest {
  170.63 +    @Test public void preLoadsTheClass() {
  170.64 +        Employer em = Models.fromRaw(BrwsrCtx.EMPTY, Employer.class, this);
  170.65 +        Assert.assertNotNull(em, "Class loaded");
  170.66 +        em.applyBindings();
  170.67 +    }
  170.68 +}
   171.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   171.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/JSONListTest.java	Tue Jan 07 08:21:57 2014 +0100
   171.3 @@ -0,0 +1,192 @@
   171.4 +/**
   171.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   171.6 + *
   171.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   171.8 + *
   171.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  171.10 + * Other names may be trademarks of their respective owners.
  171.11 + *
  171.12 + * The contents of this file are subject to the terms of either the GNU
  171.13 + * General Public License Version 2 only ("GPL") or the Common
  171.14 + * Development and Distribution License("CDDL") (collectively, the
  171.15 + * "License"). You may not use this file except in compliance with the
  171.16 + * License. You can obtain a copy of the License at
  171.17 + * http://www.netbeans.org/cddl-gplv2.html
  171.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  171.19 + * specific language governing permissions and limitations under the
  171.20 + * License.  When distributing the software, include this License Header
  171.21 + * Notice in each file and include the License file at
  171.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  171.23 + * particular file as subject to the "Classpath" exception as provided
  171.24 + * by Oracle in the GPL Version 2 section of the License file that
  171.25 + * accompanied this code. If applicable, add the following below the
  171.26 + * License Header, with the fields enclosed by brackets [] replaced by
  171.27 + * your own identifying information:
  171.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  171.29 + *
  171.30 + * Contributor(s):
  171.31 + *
  171.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  171.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  171.34 + *
  171.35 + * If you wish your version of this file to be governed by only the CDDL
  171.36 + * or only the GPL Version 2, indicate your decision by adding
  171.37 + * "[Contributor] elects to include this software in this distribution
  171.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  171.39 + * single choice of license, a recipient has the option to distribute
  171.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  171.41 + * to extend the choice of license to its licensees as provided above.
  171.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  171.43 + * Version 2 license, then the option applies only if the new code is
  171.44 + * made subject to such option by the copyright holder.
  171.45 + */
  171.46 +package org.netbeans.html.json.impl;
  171.47 +
  171.48 +import java.util.HashMap;
  171.49 +import java.util.Map;
  171.50 +import net.java.html.BrwsrCtx;
  171.51 +import net.java.html.json.Models;
  171.52 +import net.java.html.json.People;
  171.53 +import net.java.html.json.Person;
  171.54 +import net.java.html.json.Sex;
  171.55 +import org.apidesign.html.context.spi.Contexts;
  171.56 +import org.apidesign.html.json.spi.FunctionBinding;
  171.57 +import org.apidesign.html.json.spi.PropertyBinding;
  171.58 +import org.apidesign.html.json.spi.Technology;
  171.59 +import static org.testng.Assert.*;
  171.60 +import org.testng.annotations.BeforeMethod;
  171.61 +import org.testng.annotations.Test;
  171.62 +
  171.63 +/**
  171.64 + *
  171.65 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  171.66 + */
  171.67 +public class JSONListTest implements Technology<Object> {
  171.68 +    private boolean replaceArray;
  171.69 +    private final Map<String,PropertyBinding> bindings = new HashMap<String,PropertyBinding>();
  171.70 +    
  171.71 +    public JSONListTest() {
  171.72 +    }
  171.73 +    
  171.74 +    @BeforeMethod public void clear() {
  171.75 +        replaceArray = false;
  171.76 +    }
  171.77 +
  171.78 +    @Test public void testConvertorOnAnObject() {
  171.79 +        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
  171.80 +        
  171.81 +        Person p = Models.bind(new Person(), c);
  171.82 +        p.setFirstName("1");
  171.83 +        p.setLastName("2");
  171.84 +        p.setSex(Sex.MALE);
  171.85 +
  171.86 +        Object real = JSON.find(p);
  171.87 +        assertEquals(this, real, "I am the right model");
  171.88 +    }
  171.89 +    
  171.90 +    @Test public void testConvertorOnAnArray() {
  171.91 +        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
  171.92 +        
  171.93 +        Person p = Models.bind(new Person(), c);
  171.94 +        p.setFirstName("1");
  171.95 +        p.setLastName("2");
  171.96 +        p.setSex(Sex.MALE);
  171.97 +        
  171.98 +        People people = Models.bind(new People(p), c).applyBindings();
  171.99 +        assertEquals(people.getInfo().toString(), "[{\"firstName\":\"1\",\"lastName\":\"2\",\"sex\":\"MALE\"}]", "Converted to real JSON");
 171.100 +        
 171.101 +        PropertyBinding pb = bindings.get("info");
 171.102 +        assertNotNull(pb, "Binding for info found");
 171.103 +        
 171.104 +        Object real = pb.getValue();
 171.105 +        assertTrue(real instanceof Object[], "It is an array: " + real);
 171.106 +        Object[] arr = (Object[])real;
 171.107 +        assertEquals(arr.length, 1, "Size is one");
 171.108 +        assertEquals(this, arr[0], "I am the right model");
 171.109 +    }
 171.110 +    
 171.111 +    @Test public void testNicknames() {
 171.112 +        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
 171.113 +        
 171.114 +        People people = Models.bind(new People(), c).applyBindings();
 171.115 +        people.getNicknames().add("One");
 171.116 +        people.getNicknames().add("Two");
 171.117 +        
 171.118 +        PropertyBinding pb = bindings.get("nicknames");
 171.119 +        assertNotNull(pb, "Binding for info found");
 171.120 +        
 171.121 +        Object real = pb.getValue();
 171.122 +        assertTrue(real instanceof Object[], "It is an array: " + real);
 171.123 +        Object[] arr = (Object[])real;
 171.124 +        assertEquals(arr.length, 2, "Length two");
 171.125 +        assertEquals(arr[0], "One", "Text should be in the model");
 171.126 +        assertEquals(arr[1], "Two", "2nd text in the model");
 171.127 +    }
 171.128 +    
 171.129 +    @Test public void testConvertorOnAnArrayWithWrapper() {
 171.130 +        this.replaceArray = true;
 171.131 +        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
 171.132 +        
 171.133 +        Person p = Models.bind(new Person(), c);
 171.134 +        p.setFirstName("1");
 171.135 +        p.setLastName("2");
 171.136 +        p.setSex(Sex.MALE);
 171.137 +        
 171.138 +        People people = Models.bind(new People(), c).applyBindings();
 171.139 +        people.getInfo().add(p);
 171.140 +        
 171.141 +        Object real = JSON.find(people.getInfo());
 171.142 +        assertEquals(real, this, "I am the model of the array");
 171.143 +    }
 171.144 +
 171.145 +    @Test public void bindingsOnArray() {
 171.146 +        this.replaceArray = true;
 171.147 +        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
 171.148 +        
 171.149 +        People p = Models.bind(new People(), c).applyBindings();
 171.150 +        p.getAge().add(30);
 171.151 +        
 171.152 +        PropertyBinding pb = bindings.get("age");
 171.153 +        assertNotNull(pb, "There is a binding for age list");
 171.154 +        
 171.155 +        assertEquals(pb.getValue(), this, "I am the model of the array");
 171.156 +    }
 171.157 +
 171.158 +    @Override
 171.159 +    public Object wrapModel(Object model) {
 171.160 +        return this;
 171.161 +    }
 171.162 +
 171.163 +    @Override
 171.164 +    public void bind(PropertyBinding b, Object model, Object data) {
 171.165 +        bindings.put(b.getPropertyName(), b);
 171.166 +    }
 171.167 +
 171.168 +    @Override
 171.169 +    public void valueHasMutated(Object data, String propertyName) {
 171.170 +    }
 171.171 +
 171.172 +    @Override
 171.173 +    public void expose(FunctionBinding fb, Object model, Object d) {
 171.174 +    }
 171.175 +
 171.176 +    @Override
 171.177 +    public void applyBindings(Object data) {
 171.178 +    }
 171.179 +
 171.180 +    @Override
 171.181 +    public Object wrapArray(Object[] arr) {
 171.182 +        return replaceArray ? this : arr;
 171.183 +    }
 171.184 +
 171.185 +    @Override
 171.186 +    public <M> M toModel(Class<M> modelClass, Object data) {
 171.187 +        return modelClass.cast(data);
 171.188 +    }
 171.189 +
 171.190 +    @Override
 171.191 +    public void runSafe(Runnable r) {
 171.192 +        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
 171.193 +    }
 171.194 +
 171.195 +}
   172.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   172.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/JSONTest.java	Tue Jan 07 08:21:57 2014 +0100
   172.3 @@ -0,0 +1,84 @@
   172.4 +/**
   172.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   172.6 + *
   172.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   172.8 + *
   172.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  172.10 + * Other names may be trademarks of their respective owners.
  172.11 + *
  172.12 + * The contents of this file are subject to the terms of either the GNU
  172.13 + * General Public License Version 2 only ("GPL") or the Common
  172.14 + * Development and Distribution License("CDDL") (collectively, the
  172.15 + * "License"). You may not use this file except in compliance with the
  172.16 + * License. You can obtain a copy of the License at
  172.17 + * http://www.netbeans.org/cddl-gplv2.html
  172.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  172.19 + * specific language governing permissions and limitations under the
  172.20 + * License.  When distributing the software, include this License Header
  172.21 + * Notice in each file and include the License file at
  172.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  172.23 + * particular file as subject to the "Classpath" exception as provided
  172.24 + * by Oracle in the GPL Version 2 section of the License file that
  172.25 + * accompanied this code. If applicable, add the following below the
  172.26 + * License Header, with the fields enclosed by brackets [] replaced by
  172.27 + * your own identifying information:
  172.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  172.29 + *
  172.30 + * Contributor(s):
  172.31 + *
  172.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  172.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  172.34 + *
  172.35 + * If you wish your version of this file to be governed by only the CDDL
  172.36 + * or only the GPL Version 2, indicate your decision by adding
  172.37 + * "[Contributor] elects to include this software in this distribution
  172.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  172.39 + * single choice of license, a recipient has the option to distribute
  172.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  172.41 + * to extend the choice of license to its licensees as provided above.
  172.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  172.43 + * Version 2 license, then the option applies only if the new code is
  172.44 + * made subject to such option by the copyright holder.
  172.45 + */
  172.46 +package org.netbeans.html.json.impl;
  172.47 +
  172.48 +import static org.testng.Assert.*;
  172.49 +import org.testng.annotations.Test;
  172.50 +
  172.51 +/**
  172.52 + *
  172.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  172.54 + */
  172.55 +public class JSONTest {
  172.56 +    
  172.57 +    public JSONTest() {
  172.58 +    }
  172.59 +
  172.60 +    @Test public void longToStringValue() {
  172.61 +        assertEquals(JSON.stringValue(Long.valueOf(1)), "1");
  172.62 +    }
  172.63 +    
  172.64 +    @Test public void booleanIsSortOfNumber() {
  172.65 +        assertEquals(JSON.numberValue(Boolean.TRUE), Integer.valueOf(1));
  172.66 +        assertEquals(JSON.numberValue(Boolean.FALSE), Integer.valueOf(0));
  172.67 +    }
  172.68 +    
  172.69 +    @Test public void numberToChar() {
  172.70 +        assertEquals(JSON.charValue(65), Character.valueOf('A'));
  172.71 +    }
  172.72 +    @Test public void booleanToChar() {
  172.73 +        assertEquals(JSON.charValue(false), Character.valueOf((char)0));
  172.74 +        assertEquals(JSON.charValue(true), Character.valueOf((char)1));
  172.75 +    }
  172.76 +    @Test public void stringToChar() {
  172.77 +        assertEquals(JSON.charValue("Ahoj"), Character.valueOf('A'));
  172.78 +    }
  172.79 +    @Test public void stringToBoolean() {
  172.80 +        assertEquals(JSON.boolValue("false"), Boolean.FALSE);
  172.81 +        assertEquals(JSON.boolValue("True"), Boolean.TRUE);
  172.82 +    }
  172.83 +    @Test public void numberToBoolean() {
  172.84 +        assertEquals(JSON.boolValue(0), Boolean.FALSE);
  172.85 +        assertEquals(JSON.boolValue(1), Boolean.TRUE);
  172.86 +    }
  172.87 +}
   173.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   173.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/NoPropertiesTest.java	Tue Jan 07 08:21:57 2014 +0100
   173.3 @@ -0,0 +1,55 @@
   173.4 +/**
   173.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   173.6 + *
   173.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   173.8 + *
   173.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  173.10 + * Other names may be trademarks of their respective owners.
  173.11 + *
  173.12 + * The contents of this file are subject to the terms of either the GNU
  173.13 + * General Public License Version 2 only ("GPL") or the Common
  173.14 + * Development and Distribution License("CDDL") (collectively, the
  173.15 + * "License"). You may not use this file except in compliance with the
  173.16 + * License. You can obtain a copy of the License at
  173.17 + * http://www.netbeans.org/cddl-gplv2.html
  173.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  173.19 + * specific language governing permissions and limitations under the
  173.20 + * License.  When distributing the software, include this License Header
  173.21 + * Notice in each file and include the License file at
  173.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  173.23 + * particular file as subject to the "Classpath" exception as provided
  173.24 + * by Oracle in the GPL Version 2 section of the License file that
  173.25 + * accompanied this code. If applicable, add the following below the
  173.26 + * License Header, with the fields enclosed by brackets [] replaced by
  173.27 + * your own identifying information:
  173.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  173.29 + *
  173.30 + * Contributor(s):
  173.31 + *
  173.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  173.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  173.34 + *
  173.35 + * If you wish your version of this file to be governed by only the CDDL
  173.36 + * or only the GPL Version 2, indicate your decision by adding
  173.37 + * "[Contributor] elects to include this software in this distribution
  173.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  173.39 + * single choice of license, a recipient has the option to distribute
  173.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  173.41 + * to extend the choice of license to its licensees as provided above.
  173.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  173.43 + * Version 2 license, then the option applies only if the new code is
  173.44 + * made subject to such option by the copyright holder.
  173.45 + */
  173.46 +package org.netbeans.html.json.impl;
  173.47 +
  173.48 +import net.java.html.json.Model;
  173.49 +
  173.50 +/** Originally could not compile.
  173.51 + *
  173.52 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  173.53 + */
  173.54 +@Model(className="NoProperties", properties = {
  173.55 +})
  173.56 +public class NoPropertiesTest {
  173.57 +    
  173.58 +}
   174.1 --- a/ko-archetype-test/pom.xml	Thu Dec 19 17:11:01 2013 +0100
   174.2 +++ b/ko-archetype-test/pom.xml	Tue Jan 07 08:21:57 2014 +0100
   174.3 @@ -2,11 +2,11 @@
   174.4  <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">
   174.5      <modelVersion>4.0.0</modelVersion>
   174.6      <parent>
   174.7 -        <groupId>org.apidesign</groupId>
   174.8 -        <artifactId>html</artifactId>
   174.9 +        <groupId>org.netbeans.html</groupId>
  174.10 +        <artifactId>pom</artifactId>
  174.11          <version>0.7-SNAPSHOT</version>
  174.12      </parent>
  174.13 -    <groupId>org.apidesign.html</groupId>
  174.14 +    <groupId>org.netbeans.html</groupId>
  174.15      <artifactId>ko-archetype-test</artifactId>
  174.16      <version>0.7-SNAPSHOT</version>
  174.17      <name>Knockout 4 Java Archetype Test</name>
   175.1 --- a/ko-archetype-test/src/test/java/org/apidesign/html/archetype/test/ArchetypeVersionTest.java	Thu Dec 19 17:11:01 2013 +0100
   175.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   175.3 @@ -1,106 +0,0 @@
   175.4 -/**
   175.5 - * HTML via Java(tm) Language Bindings
   175.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   175.7 - *
   175.8 - * This program is free software: you can redistribute it and/or modify
   175.9 - * it under the terms of the GNU General Public License as published by
  175.10 - * the Free Software Foundation, version 2 of the License.
  175.11 - *
  175.12 - * This program is distributed in the hope that it will be useful,
  175.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  175.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  175.15 - * GNU General Public License for more details. apidesign.org
  175.16 - * designates this particular file as subject to the
  175.17 - * "Classpath" exception as provided by apidesign.org
  175.18 - * in the License file that accompanied this code.
  175.19 - *
  175.20 - * You should have received a copy of the GNU General Public License
  175.21 - * along with this program. Look for COPYING file in the top folder.
  175.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  175.23 - */
  175.24 -package org.apidesign.html.archetype.test;
  175.25 -
  175.26 -import java.io.IOException;
  175.27 -import java.net.URL;
  175.28 -import javax.xml.XMLConstants;
  175.29 -import javax.xml.parsers.DocumentBuilderFactory;
  175.30 -import javax.xml.parsers.ParserConfigurationException;
  175.31 -import javax.xml.xpath.XPathConstants;
  175.32 -import javax.xml.xpath.XPathExpression;
  175.33 -import javax.xml.xpath.XPathExpressionException;
  175.34 -import javax.xml.xpath.XPathFactory;
  175.35 -import javax.xml.xpath.XPathFactoryConfigurationException;
  175.36 -import org.testng.annotations.Test;
  175.37 -import static org.testng.Assert.*;
  175.38 -import org.testng.annotations.BeforeClass;
  175.39 -import org.w3c.dom.Document;
  175.40 -import org.w3c.dom.NodeList;
  175.41 -import org.xml.sax.SAXException;
  175.42 -
  175.43 -/**
  175.44 - *
  175.45 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  175.46 - */
  175.47 -public class ArchetypeVersionTest {
  175.48 -    private String version;
  175.49 -    
  175.50 -    public ArchetypeVersionTest() {
  175.51 -    }
  175.52 -    
  175.53 -    @BeforeClass public void readCurrentVersion() throws Exception {
  175.54 -        version = findCurrentVersion();
  175.55 -        assertFalse(version.isEmpty(), "There should be some version string");
  175.56 -    }
  175.57 -    
  175.58 -
  175.59 -    @Test public void testComparePomDepsVersions() throws Exception {
  175.60 -        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
  175.61 -        URL r = l.getResource("archetype-resources/pom.xml");
  175.62 -        assertNotNull(r, "Archetype pom found");
  175.63 -        
  175.64 -        final XPathFactory fact = XPathFactory.newInstance();
  175.65 -        XPathExpression xp2 = fact.newXPath().compile(
  175.66 -            "//properties/net.java.html.version/text()"
  175.67 -        );
  175.68 -        
  175.69 -        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
  175.70 -        String arch = (String) xp2.evaluate(dom, XPathConstants.STRING);
  175.71 -
  175.72 -        assertEquals(arch, version, "net.java.html.json dependency needs to be on latest version");
  175.73 -    }
  175.74 -    
  175.75 -    @Test public void testNbActions() throws Exception {
  175.76 -        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
  175.77 -        URL r = l.getResource("archetype-resources/nbactions.xml");
  175.78 -        assertNotNull(r, "Archetype nb file found");
  175.79 -        
  175.80 -        final XPathFactory fact = XPathFactory.newInstance();
  175.81 -        XPathExpression xp2 = fact.newXPath().compile(
  175.82 -            "//goal/text()"
  175.83 -        );
  175.84 -        
  175.85 -        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
  175.86 -        NodeList goals = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
  175.87 -        
  175.88 -        for (int i = 0; i < goals.getLength(); i++) {
  175.89 -            String s = goals.item(i).getTextContent();
  175.90 -            if (s.contains("apidesign")) {
  175.91 -                assertFalse(s.matches(".*apidesign.*[0-9].*"), "No numbers: " + s);
  175.92 -            }
  175.93 -        }
  175.94 -    }
  175.95 -
  175.96 -    static String findCurrentVersion() throws XPathExpressionException, IOException, ParserConfigurationException, SAXException, XPathFactoryConfigurationException {
  175.97 -        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
  175.98 -        URL u = l.getResource("META-INF/maven/org.apidesign.html/knockout4j-archetype/pom.xml");
  175.99 -        assertNotNull(u, "Own pom found: " + System.getProperty("java.class.path"));
 175.100 -
 175.101 -        final XPathFactory fact = XPathFactory.newInstance();
 175.102 -        fact.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
 175.103 -
 175.104 -        XPathExpression xp = fact.newXPath().compile("project/version/text()");
 175.105 -        
 175.106 -        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(u.openStream());
 175.107 -        return xp.evaluate(dom);
 175.108 -    }
 175.109 -}
   176.1 --- a/ko-archetype-test/src/test/java/org/apidesign/html/archetype/test/VerifyArchetypeTest.java	Thu Dec 19 17:11:01 2013 +0100
   176.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   176.3 @@ -1,77 +0,0 @@
   176.4 -/**
   176.5 - * HTML via Java(tm) Language Bindings
   176.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   176.7 - *
   176.8 - * This program is free software: you can redistribute it and/or modify
   176.9 - * it under the terms of the GNU General Public License as published by
  176.10 - * the Free Software Foundation, version 2 of the License.
  176.11 - *
  176.12 - * This program is distributed in the hope that it will be useful,
  176.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  176.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  176.15 - * GNU General Public License for more details. apidesign.org
  176.16 - * designates this particular file as subject to the
  176.17 - * "Classpath" exception as provided by apidesign.org
  176.18 - * in the License file that accompanied this code.
  176.19 - *
  176.20 - * You should have received a copy of the GNU General Public License
  176.21 - * along with this program. Look for COPYING file in the top folder.
  176.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  176.23 - */
  176.24 -package org.apidesign.html.archetype.test;
  176.25 -
  176.26 -import java.io.File;
  176.27 -import java.util.Properties;
  176.28 -import org.apache.maven.it.Verifier;
  176.29 -import org.testng.annotations.Test;
  176.30 -import static org.testng.Assert.*;
  176.31 -
  176.32 -/**
  176.33 - *
  176.34 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  176.35 - */
  176.36 -public class VerifyArchetypeTest {
  176.37 -    @Test public void projectCompiles() throws Exception {
  176.38 -        final File dir = new File("target/tests/fxcompile/").getAbsoluteFile();
  176.39 -        generateFromArchetype(dir);
  176.40 -        
  176.41 -        File created = new File(dir, "o-a-test");
  176.42 -        assertTrue(created.isDirectory(), "Project created");
  176.43 -        assertTrue(new File(created, "pom.xml").isFile(), "Pom file is in there");
  176.44 -        
  176.45 -        Verifier v = new Verifier(created.getAbsolutePath());
  176.46 -        v.executeGoal("verify");
  176.47 -        
  176.48 -        v.verifyErrorFreeLog();
  176.49 -        
  176.50 -        for (String l : v.loadFile(v.getBasedir(), v.getLogFileName(), false)) {
  176.51 -            if (l.contains("j2js")) {
  176.52 -                fail("No pre-compilaton:\n" + l);
  176.53 -            }
  176.54 -        }
  176.55 -        
  176.56 -        v.verifyTextInLog("fxcompile/o-a-test/target/o-a-test-1.0-SNAPSHOT-html.java.net.zip");
  176.57 -    }
  176.58 -    
  176.59 -    private Verifier generateFromArchetype(final File dir, String... params) throws Exception {
  176.60 -        Verifier v = new Verifier(dir.getAbsolutePath());
  176.61 -        v.setAutoclean(false);
  176.62 -        v.setLogFileName("generate.log");
  176.63 -        v.deleteDirectory("");
  176.64 -        dir.mkdirs();
  176.65 -        Properties sysProp = v.getSystemProperties();
  176.66 -        sysProp.put("groupId", "org.apidesign.test");
  176.67 -        sysProp.put("artifactId", "o-a-test");
  176.68 -        sysProp.put("package", "org.apidesign.test.oat");
  176.69 -        sysProp.put("archetypeGroupId", "org.apidesign.html");
  176.70 -        sysProp.put("archetypeArtifactId", "knockout4j-archetype");
  176.71 -        sysProp.put("archetypeVersion", ArchetypeVersionTest.findCurrentVersion());
  176.72 -        
  176.73 -        for (String p : params) {
  176.74 -            v.addCliOption(p);
  176.75 -        }
  176.76 -        v.executeGoal("archetype:generate");
  176.77 -        v.verifyErrorFreeLog();
  176.78 -        return v;
  176.79 -    }
  176.80 -}
   177.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   177.2 +++ b/ko-archetype-test/src/test/java/org/netbeans/html/archetype/test/ArchetypeVersionTest.java	Tue Jan 07 08:21:57 2014 +0100
   177.3 @@ -0,0 +1,128 @@
   177.4 +/**
   177.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   177.6 + *
   177.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   177.8 + *
   177.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  177.10 + * Other names may be trademarks of their respective owners.
  177.11 + *
  177.12 + * The contents of this file are subject to the terms of either the GNU
  177.13 + * General Public License Version 2 only ("GPL") or the Common
  177.14 + * Development and Distribution License("CDDL") (collectively, the
  177.15 + * "License"). You may not use this file except in compliance with the
  177.16 + * License. You can obtain a copy of the License at
  177.17 + * http://www.netbeans.org/cddl-gplv2.html
  177.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  177.19 + * specific language governing permissions and limitations under the
  177.20 + * License.  When distributing the software, include this License Header
  177.21 + * Notice in each file and include the License file at
  177.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  177.23 + * particular file as subject to the "Classpath" exception as provided
  177.24 + * by Oracle in the GPL Version 2 section of the License file that
  177.25 + * accompanied this code. If applicable, add the following below the
  177.26 + * License Header, with the fields enclosed by brackets [] replaced by
  177.27 + * your own identifying information:
  177.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  177.29 + *
  177.30 + * Contributor(s):
  177.31 + *
  177.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  177.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  177.34 + *
  177.35 + * If you wish your version of this file to be governed by only the CDDL
  177.36 + * or only the GPL Version 2, indicate your decision by adding
  177.37 + * "[Contributor] elects to include this software in this distribution
  177.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  177.39 + * single choice of license, a recipient has the option to distribute
  177.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  177.41 + * to extend the choice of license to its licensees as provided above.
  177.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  177.43 + * Version 2 license, then the option applies only if the new code is
  177.44 + * made subject to such option by the copyright holder.
  177.45 + */
  177.46 +package org.netbeans.html.archetype.test;
  177.47 +
  177.48 +import java.io.IOException;
  177.49 +import java.net.URL;
  177.50 +import javax.xml.XMLConstants;
  177.51 +import javax.xml.parsers.DocumentBuilderFactory;
  177.52 +import javax.xml.parsers.ParserConfigurationException;
  177.53 +import javax.xml.xpath.XPathConstants;
  177.54 +import javax.xml.xpath.XPathExpression;
  177.55 +import javax.xml.xpath.XPathExpressionException;
  177.56 +import javax.xml.xpath.XPathFactory;
  177.57 +import javax.xml.xpath.XPathFactoryConfigurationException;
  177.58 +import org.testng.annotations.Test;
  177.59 +import static org.testng.Assert.*;
  177.60 +import org.testng.annotations.BeforeClass;
  177.61 +import org.w3c.dom.Document;
  177.62 +import org.w3c.dom.NodeList;
  177.63 +import org.xml.sax.SAXException;
  177.64 +
  177.65 +/**
  177.66 + *
  177.67 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  177.68 + */
  177.69 +public class ArchetypeVersionTest {
  177.70 +    private String version;
  177.71 +    
  177.72 +    public ArchetypeVersionTest() {
  177.73 +    }
  177.74 +    
  177.75 +    @BeforeClass public void readCurrentVersion() throws Exception {
  177.76 +        version = findCurrentVersion();
  177.77 +        assertFalse(version.isEmpty(), "There should be some version string");
  177.78 +    }
  177.79 +    
  177.80 +
  177.81 +    @Test public void testComparePomDepsVersions() throws Exception {
  177.82 +        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
  177.83 +        URL r = l.getResource("archetype-resources/pom.xml");
  177.84 +        assertNotNull(r, "Archetype pom found");
  177.85 +        
  177.86 +        final XPathFactory fact = XPathFactory.newInstance();
  177.87 +        XPathExpression xp2 = fact.newXPath().compile(
  177.88 +            "//properties/net.java.html.version/text()"
  177.89 +        );
  177.90 +        
  177.91 +        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
  177.92 +        String arch = (String) xp2.evaluate(dom, XPathConstants.STRING);
  177.93 +
  177.94 +        assertEquals(arch, version, "net.java.html.json dependency needs to be on latest version");
  177.95 +    }
  177.96 +    
  177.97 +    @Test public void testNbActions() throws Exception {
  177.98 +        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
  177.99 +        URL r = l.getResource("archetype-resources/nbactions.xml");
 177.100 +        assertNotNull(r, "Archetype nb file found");
 177.101 +        
 177.102 +        final XPathFactory fact = XPathFactory.newInstance();
 177.103 +        XPathExpression xp2 = fact.newXPath().compile(
 177.104 +            "//goal/text()"
 177.105 +        );
 177.106 +        
 177.107 +        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
 177.108 +        NodeList goals = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
 177.109 +        
 177.110 +        for (int i = 0; i < goals.getLength(); i++) {
 177.111 +            String s = goals.item(i).getTextContent();
 177.112 +            if (s.contains("netbeans")) {
 177.113 +                assertFalse(s.matches(".*netbeans.*[0-9].*"), "No numbers: " + s);
 177.114 +            }
 177.115 +        }
 177.116 +    }
 177.117 +
 177.118 +    static String findCurrentVersion() throws XPathExpressionException, IOException, ParserConfigurationException, SAXException, XPathFactoryConfigurationException {
 177.119 +        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
 177.120 +        URL u = l.getResource("META-INF/maven/org.netbeans.html/knockout4j-archetype/pom.xml");
 177.121 +        assertNotNull(u, "Own pom found: " + System.getProperty("java.class.path"));
 177.122 +
 177.123 +        final XPathFactory fact = XPathFactory.newInstance();
 177.124 +        fact.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
 177.125 +
 177.126 +        XPathExpression xp = fact.newXPath().compile("project/version/text()");
 177.127 +        
 177.128 +        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(u.openStream());
 177.129 +        return xp.evaluate(dom);
 177.130 +    }
 177.131 +}
   178.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   178.2 +++ b/ko-archetype-test/src/test/java/org/netbeans/html/archetype/test/VerifyArchetypeTest.java	Tue Jan 07 08:21:57 2014 +0100
   178.3 @@ -0,0 +1,99 @@
   178.4 +/**
   178.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   178.6 + *
   178.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   178.8 + *
   178.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  178.10 + * Other names may be trademarks of their respective owners.
  178.11 + *
  178.12 + * The contents of this file are subject to the terms of either the GNU
  178.13 + * General Public License Version 2 only ("GPL") or the Common
  178.14 + * Development and Distribution License("CDDL") (collectively, the
  178.15 + * "License"). You may not use this file except in compliance with the
  178.16 + * License. You can obtain a copy of the License at
  178.17 + * http://www.netbeans.org/cddl-gplv2.html
  178.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  178.19 + * specific language governing permissions and limitations under the
  178.20 + * License.  When distributing the software, include this License Header
  178.21 + * Notice in each file and include the License file at
  178.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  178.23 + * particular file as subject to the "Classpath" exception as provided
  178.24 + * by Oracle in the GPL Version 2 section of the License file that
  178.25 + * accompanied this code. If applicable, add the following below the
  178.26 + * License Header, with the fields enclosed by brackets [] replaced by
  178.27 + * your own identifying information:
  178.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  178.29 + *
  178.30 + * Contributor(s):
  178.31 + *
  178.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  178.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  178.34 + *
  178.35 + * If you wish your version of this file to be governed by only the CDDL
  178.36 + * or only the GPL Version 2, indicate your decision by adding
  178.37 + * "[Contributor] elects to include this software in this distribution
  178.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  178.39 + * single choice of license, a recipient has the option to distribute
  178.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  178.41 + * to extend the choice of license to its licensees as provided above.
  178.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  178.43 + * Version 2 license, then the option applies only if the new code is
  178.44 + * made subject to such option by the copyright holder.
  178.45 + */
  178.46 +package org.netbeans.html.archetype.test;
  178.47 +
  178.48 +import java.io.File;
  178.49 +import java.util.Properties;
  178.50 +import org.apache.maven.it.Verifier;
  178.51 +import org.testng.annotations.Test;
  178.52 +import static org.testng.Assert.*;
  178.53 +
  178.54 +/**
  178.55 + *
  178.56 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  178.57 + */
  178.58 +public class VerifyArchetypeTest {
  178.59 +    @Test public void projectCompiles() throws Exception {
  178.60 +        final File dir = new File("target/tests/fxcompile/").getAbsoluteFile();
  178.61 +        generateFromArchetype(dir);
  178.62 +        
  178.63 +        File created = new File(dir, "o-a-test");
  178.64 +        assertTrue(created.isDirectory(), "Project created");
  178.65 +        assertTrue(new File(created, "pom.xml").isFile(), "Pom file is in there");
  178.66 +        
  178.67 +        Verifier v = new Verifier(created.getAbsolutePath());
  178.68 +        v.executeGoal("verify");
  178.69 +        
  178.70 +        v.verifyErrorFreeLog();
  178.71 +        
  178.72 +        for (String l : v.loadFile(v.getBasedir(), v.getLogFileName(), false)) {
  178.73 +            if (l.contains("j2js")) {
  178.74 +                fail("No pre-compilaton:\n" + l);
  178.75 +            }
  178.76 +        }
  178.77 +        
  178.78 +        v.verifyTextInLog("fxcompile/o-a-test/target/o-a-test-1.0-SNAPSHOT-html.java.net.zip");
  178.79 +    }
  178.80 +    
  178.81 +    private Verifier generateFromArchetype(final File dir, String... params) throws Exception {
  178.82 +        Verifier v = new Verifier(dir.getAbsolutePath());
  178.83 +        v.setAutoclean(false);
  178.84 +        v.setLogFileName("generate.log");
  178.85 +        v.deleteDirectory("");
  178.86 +        dir.mkdirs();
  178.87 +        Properties sysProp = v.getSystemProperties();
  178.88 +        sysProp.put("groupId", "org.someuser.test");
  178.89 +        sysProp.put("artifactId", "o-a-test");
  178.90 +        sysProp.put("package", "org.someuser.test.oat");
  178.91 +        sysProp.put("archetypeGroupId", "org.netbeans.html");
  178.92 +        sysProp.put("archetypeArtifactId", "knockout4j-archetype");
  178.93 +        sysProp.put("archetypeVersion", ArchetypeVersionTest.findCurrentVersion());
  178.94 +        
  178.95 +        for (String p : params) {
  178.96 +            v.addCliOption(p);
  178.97 +        }
  178.98 +        v.executeGoal("archetype:generate");
  178.99 +        v.verifyErrorFreeLog();
 178.100 +        return v;
 178.101 +    }
 178.102 +}
   179.1 --- a/ko-archetype/pom.xml	Thu Dec 19 17:11:01 2013 +0100
   179.2 +++ b/ko-archetype/pom.xml	Tue Jan 07 08:21:57 2014 +0100
   179.3 @@ -2,11 +2,11 @@
   179.4  <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">
   179.5    <modelVersion>4.0.0</modelVersion>
   179.6    <parent>
   179.7 -    <artifactId>html</artifactId>
   179.8 -    <groupId>org.apidesign</groupId>
   179.9 +    <groupId>org.netbeans.html</groupId>
  179.10 +    <artifactId>pom</artifactId>
  179.11      <version>0.7-SNAPSHOT</version>
  179.12    </parent>
  179.13 -  <groupId>org.apidesign.html</groupId>
  179.14 +  <groupId>org.netbeans.html</groupId>
  179.15    <artifactId>knockout4j-archetype</artifactId>
  179.16    <version>0.7-SNAPSHOT</version>
  179.17    <packaging>jar</packaging>
   180.1 --- a/ko-archetype/src/main/java/org/apidesign/html/archetype/package-info.java	Thu Dec 19 17:11:01 2013 +0100
   180.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   180.3 @@ -1,21 +0,0 @@
   180.4 -/**
   180.5 - * HTML via Java(tm) Language Bindings
   180.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   180.7 - *
   180.8 - * This program is free software: you can redistribute it and/or modify
   180.9 - * it under the terms of the GNU General Public License as published by
  180.10 - * the Free Software Foundation, version 2 of the License.
  180.11 - *
  180.12 - * This program is distributed in the hope that it will be useful,
  180.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  180.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  180.15 - * GNU General Public License for more details. apidesign.org
  180.16 - * designates this particular file as subject to the
  180.17 - * "Classpath" exception as provided by apidesign.org
  180.18 - * in the License file that accompanied this code.
  180.19 - *
  180.20 - * You should have received a copy of the GNU General Public License
  180.21 - * along with this program. Look for COPYING file in the top folder.
  180.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  180.23 - */
  180.24 -package org.apidesign.html.archetype;
   181.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   181.2 +++ b/ko-archetype/src/main/java/org/netbeans/html/archetype/package-info.java	Tue Jan 07 08:21:57 2014 +0100
   181.3 @@ -0,0 +1,43 @@
   181.4 +/**
   181.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   181.6 + *
   181.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   181.8 + *
   181.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  181.10 + * Other names may be trademarks of their respective owners.
  181.11 + *
  181.12 + * The contents of this file are subject to the terms of either the GNU
  181.13 + * General Public License Version 2 only ("GPL") or the Common
  181.14 + * Development and Distribution License("CDDL") (collectively, the
  181.15 + * "License"). You may not use this file except in compliance with the
  181.16 + * License. You can obtain a copy of the License at
  181.17 + * http://www.netbeans.org/cddl-gplv2.html
  181.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  181.19 + * specific language governing permissions and limitations under the
  181.20 + * License.  When distributing the software, include this License Header
  181.21 + * Notice in each file and include the License file at
  181.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  181.23 + * particular file as subject to the "Classpath" exception as provided
  181.24 + * by Oracle in the GPL Version 2 section of the License file that
  181.25 + * accompanied this code. If applicable, add the following below the
  181.26 + * License Header, with the fields enclosed by brackets [] replaced by
  181.27 + * your own identifying information:
  181.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  181.29 + *
  181.30 + * Contributor(s):
  181.31 + *
  181.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  181.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  181.34 + *
  181.35 + * If you wish your version of this file to be governed by only the CDDL
  181.36 + * or only the GPL Version 2, indicate your decision by adding
  181.37 + * "[Contributor] elects to include this software in this distribution
  181.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  181.39 + * single choice of license, a recipient has the option to distribute
  181.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  181.41 + * to extend the choice of license to its licensees as provided above.
  181.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  181.43 + * Version 2 license, then the option applies only if the new code is
  181.44 + * made subject to such option by the copyright holder.
  181.45 + */
  181.46 +package org.netbeans.html.archetype;
   182.1 --- a/ko-archetype/src/main/resources/archetype-resources/pom.xml	Thu Dec 19 17:11:01 2013 +0100
   182.2 +++ b/ko-archetype/src/main/resources/archetype-resources/pom.xml	Tue Jan 07 08:21:57 2014 +0100
   182.3 @@ -101,24 +101,24 @@
   182.4    </build>
   182.5    <dependencies>
   182.6      <dependency>
   182.7 -        <groupId>org.apidesign.html</groupId>
   182.8 +        <groupId>org.netbeans.html</groupId>
   182.9          <artifactId>net.java.html.json</artifactId>
  182.10          <version>\${net.java.html.version}</version>
  182.11      </dependency>
  182.12      <dependency>
  182.13 -        <groupId>org.apidesign.html</groupId>
  182.14 +        <groupId>org.netbeans.html</groupId>
  182.15          <artifactId>net.java.html.boot</artifactId>
  182.16          <version>\${net.java.html.version}</version>
  182.17      </dependency>
  182.18      <dependency>
  182.19 -        <groupId>org.apidesign.html</groupId>
  182.20 +        <groupId>org.netbeans.html</groupId>
  182.21          <artifactId>ko-fx</artifactId>
  182.22          <version>\${net.java.html.version}</version>
  182.23          <scope>runtime</scope>
  182.24      </dependency>
  182.25      <dependency>
  182.26 -        <groupId>org.apidesign.html</groupId>
  182.27 -        <artifactId>boot-fx</artifactId>
  182.28 +        <groupId>org.netbeans.html</groupId>
  182.29 +        <artifactId>net.java.html.boot.fx</artifactId>
  182.30          <version>\${net.java.html.version}</version>
  182.31          <scope>runtime</scope>
  182.32      </dependency>
   183.1 --- a/ko-fx/pom.xml	Thu Dec 19 17:11:01 2013 +0100
   183.2 +++ b/ko-fx/pom.xml	Tue Jan 07 08:21:57 2014 +0100
   183.3 @@ -2,11 +2,11 @@
   183.4  <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">
   183.5    <modelVersion>4.0.0</modelVersion>
   183.6    <parent>
   183.7 -    <groupId>org.apidesign</groupId>
   183.8 -    <artifactId>html</artifactId>
   183.9 +    <groupId>org.netbeans.html</groupId>
  183.10 +    <artifactId>pom</artifactId>
  183.11      <version>0.7-SNAPSHOT</version>
  183.12    </parent>
  183.13 -  <groupId>org.apidesign.html</groupId>
  183.14 +  <groupId>org.netbeans.html</groupId>
  183.15    <artifactId>ko-fx</artifactId>
  183.16    <version>0.7-SNAPSHOT</version>
  183.17    <packaging>bundle</packaging>
  183.18 @@ -14,6 +14,7 @@
  183.19    <url>http://maven.apache.org</url>
  183.20    <properties>
  183.21      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  183.22 +    <bundleSymbolicName>org.netbeans.html.ko-fx</bundleSymbolicName>
  183.23    </properties>
  183.24    <build>
  183.25        <plugins>
  183.26 @@ -52,7 +53,7 @@
  183.27          <artifactId>org.json-osgi</artifactId>
  183.28      </dependency>
  183.29      <dependency>
  183.30 -      <groupId>org.apidesign.html</groupId>
  183.31 +      <groupId>org.netbeans.html</groupId>
  183.32        <artifactId>net.java.html.json</artifactId>
  183.33        <version>${project.version}</version>
  183.34      </dependency>
  183.35 @@ -73,14 +74,14 @@
  183.36        <scope>provided</scope>
  183.37      </dependency>
  183.38      <dependency>
  183.39 -      <groupId>org.apidesign.html</groupId>
  183.40 +      <groupId>org.netbeans.html</groupId>
  183.41        <artifactId>net.java.html.boot</artifactId>
  183.42        <version>${project.version}</version>
  183.43        <type>jar</type>
  183.44      </dependency>
  183.45      <dependency>
  183.46        <groupId>${project.groupId}</groupId>
  183.47 -      <artifactId>boot-fx</artifactId>
  183.48 +      <artifactId>net.java.html.boot.fx</artifactId>
  183.49        <version>${project.version}</version>
  183.50        <scope>test</scope>
  183.51      </dependency>
   184.1 --- a/ko-fx/src/main/java/org/apidesign/html/kofx/Console.java	Thu Dec 19 17:11:01 2013 +0100
   184.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   184.3 @@ -1,59 +0,0 @@
   184.4 -/**
   184.5 - * HTML via Java(tm) Language Bindings
   184.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   184.7 - *
   184.8 - * This program is free software: you can redistribute it and/or modify
   184.9 - * it under the terms of the GNU General Public License as published by
  184.10 - * the Free Software Foundation, version 2 of the License.
  184.11 - *
  184.12 - * This program is distributed in the hope that it will be useful,
  184.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  184.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  184.15 - * GNU General Public License for more details. apidesign.org
  184.16 - * designates this particular file as subject to the
  184.17 - * "Classpath" exception as provided by apidesign.org
  184.18 - * in the License file that accompanied this code.
  184.19 - *
  184.20 - * You should have received a copy of the GNU General Public License
  184.21 - * along with this program. Look for COPYING file in the top folder.
  184.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  184.23 - */
  184.24 -package org.apidesign.html.kofx;
  184.25 -
  184.26 -import java.util.logging.Level;
  184.27 -import java.util.logging.Logger;
  184.28 -import net.java.html.js.JavaScriptBody;
  184.29 -
  184.30 -/** This is an implementation package - just
  184.31 - * include its JAR on classpath and use official {@link Context} API
  184.32 - * to access the functionality.
  184.33 - * <p>
  184.34 - * Redirects JavaScript's messages to Java's {@link Logger}.
  184.35 - *
  184.36 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  184.37 - */
  184.38 -final class Console {
  184.39 -    private static final Logger LOG = Logger.getLogger(Console.class.getName());
  184.40 -    
  184.41 -    private Console() {
  184.42 -    }
  184.43 -
  184.44 -    static void register() {
  184.45 -        registerImpl("log", Level.INFO);
  184.46 -        registerImpl("info", Level.INFO);
  184.47 -        registerImpl("warn", Level.WARNING);
  184.48 -        registerImpl("error", Level.SEVERE);
  184.49 -    }
  184.50 -    
  184.51 -    @JavaScriptBody(args = { "attr", "l" }, 
  184.52 -        javacall = true, body = 
  184.53 -        "  window.console[attr] = function(m) {\n"
  184.54 -      + "    @org.apidesign.html.kofx.Console::log(Ljava/util/logging/Level;Ljava/lang/String;)(l, m);\n"
  184.55 -      + "  };\n"
  184.56 -    )
  184.57 -    private static native void registerImpl(String attr, Level l);
  184.58 -    
  184.59 -    static void log(Level l, String msg) {
  184.60 -        LOG.log(l, msg);
  184.61 -    }
  184.62 -}
   185.1 --- a/ko-fx/src/main/java/org/apidesign/html/kofx/FXContext.java	Thu Dec 19 17:11:01 2013 +0100
   185.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   185.3 @@ -1,200 +0,0 @@
   185.4 -/**
   185.5 - * HTML via Java(tm) Language Bindings
   185.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   185.7 - *
   185.8 - * This program is free software: you can redistribute it and/or modify
   185.9 - * it under the terms of the GNU General Public License as published by
  185.10 - * the Free Software Foundation, version 2 of the License.
  185.11 - *
  185.12 - * This program is distributed in the hope that it will be useful,
  185.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  185.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  185.15 - * GNU General Public License for more details. apidesign.org
  185.16 - * designates this particular file as subject to the
  185.17 - * "Classpath" exception as provided by apidesign.org
  185.18 - * in the License file that accompanied this code.
  185.19 - *
  185.20 - * You should have received a copy of the GNU General Public License
  185.21 - * along with this program. Look for COPYING file in the top folder.
  185.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  185.23 - */
  185.24 -package org.apidesign.html.kofx;
  185.25 -
  185.26 -import java.io.Closeable;
  185.27 -import java.io.IOException;
  185.28 -import java.io.InputStream;
  185.29 -import java.util.ServiceLoader;
  185.30 -import java.util.logging.Logger;
  185.31 -import javafx.application.Platform;
  185.32 -import net.java.html.js.JavaScriptBody;
  185.33 -import netscape.javascript.JSObject;
  185.34 -import org.apidesign.html.boot.spi.Fn;
  185.35 -import org.apidesign.html.context.spi.Contexts;
  185.36 -import org.apidesign.html.json.spi.FunctionBinding;
  185.37 -import org.apidesign.html.json.spi.JSONCall;
  185.38 -import org.apidesign.html.json.spi.PropertyBinding;
  185.39 -import org.apidesign.html.json.spi.Technology;
  185.40 -import org.apidesign.html.json.spi.Transfer;
  185.41 -import org.apidesign.html.json.spi.WSTransfer;
  185.42 -import org.openide.util.lookup.ServiceProvider;
  185.43 -
  185.44 -/** This is an implementation package - just
  185.45 - * include its JAR on classpath and use official {@link Context} API
  185.46 - * to access the functionality.
  185.47 - * <p>
  185.48 - * Registers {@link ContextProvider}, so {@link ServiceLoader} can find it.
  185.49 - *
  185.50 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  185.51 - */
  185.52 -public final class FXContext
  185.53 -implements Technology.BatchInit<JSObject>, Transfer, WSTransfer<LoadWS> {
  185.54 -    static final Logger LOG = Logger.getLogger(FXContext.class.getName());
  185.55 -    private static Boolean javaScriptEnabled;
  185.56 -    private final Fn.Presenter browserContext;
  185.57 -
  185.58 -    public FXContext(Fn.Presenter browserContext) {
  185.59 -        this.browserContext = browserContext;
  185.60 -    }
  185.61 -    
  185.62 -    @JavaScriptBody(args = {}, body = "return true;")
  185.63 -    private static boolean isJavaScriptEnabledJs() {
  185.64 -        return false;
  185.65 -    }
  185.66 -    
  185.67 -    static boolean isJavaScriptEnabled() {
  185.68 -        if (javaScriptEnabled != null) {
  185.69 -            return javaScriptEnabled;
  185.70 -        }
  185.71 -        return javaScriptEnabled = isJavaScriptEnabledJs();
  185.72 -    }
  185.73 -
  185.74 -    final boolean areWebSocketsSupported() {
  185.75 -        return LoadWS.isSupported();
  185.76 -    }
  185.77 -
  185.78 -
  185.79 -    @Override
  185.80 -    public JSObject wrapModel(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
  185.81 -        String[] propNames = new String[propArr.length];
  185.82 -        boolean[] propReadOnly = new boolean[propArr.length];
  185.83 -        Object[] propValues = new Object[propArr.length];
  185.84 -        for (int i = 0; i < propNames.length; i++) {
  185.85 -            propNames[i] = propArr[i].getPropertyName();
  185.86 -            propReadOnly[i] = propArr[i].isReadOnly();
  185.87 -            propValues[i] = propArr[i].getValue();
  185.88 -        }
  185.89 -        String[] funcNames = new String[funcArr.length];
  185.90 -        for (int i = 0; i < funcNames.length; i++) {
  185.91 -            funcNames[i] = funcArr[i].getFunctionName();
  185.92 -        }
  185.93 -        
  185.94 -        return Knockout.wrapModel(model, 
  185.95 -            propNames, propReadOnly, Knockout.toArray(propValues), propArr, 
  185.96 -            funcNames, funcArr
  185.97 -        );
  185.98 -    }
  185.99 -    
 185.100 -    @Override
 185.101 -    public JSObject wrapModel(Object model) {
 185.102 -        throw new UnsupportedOperationException();
 185.103 -    }
 185.104 -
 185.105 -    @Override
 185.106 -    public void bind(PropertyBinding b, Object model, JSObject data) {
 185.107 -        throw new UnsupportedOperationException();
 185.108 -    }
 185.109 -
 185.110 -    @Override
 185.111 -    public void valueHasMutated(JSObject data, String propertyName) {
 185.112 -        Knockout.valueHasMutated(data, propertyName);
 185.113 -    }
 185.114 -
 185.115 -    @Override
 185.116 -    public void expose(FunctionBinding fb, Object model, JSObject d) {
 185.117 -        throw new UnsupportedOperationException();
 185.118 -    }
 185.119 -
 185.120 -    @Override
 185.121 -    public void applyBindings(JSObject data) {
 185.122 -        Knockout.applyBindings(data);
 185.123 -    }
 185.124 -
 185.125 -    @Override
 185.126 -    public Object wrapArray(Object[] arr) {
 185.127 -        return Knockout.toArray(arr);
 185.128 -    }
 185.129 -
 185.130 -    @Override
 185.131 -    public void extract(Object obj, String[] props, Object[] values) {
 185.132 -        LoadJSON.extractJSON(obj, props, values);
 185.133 -    }
 185.134 -
 185.135 -    @Override
 185.136 -    public void loadJSON(final JSONCall call) {
 185.137 -        LoadJSON.loadJSON(call);
 185.138 -    }
 185.139 -
 185.140 -    @Override
 185.141 -    public <M> M toModel(Class<M> modelClass, Object data) {
 185.142 -        if (data instanceof JSObject) {
 185.143 -            data = ((JSObject)data).getMember("ko-fx.model"); // NOI18N
 185.144 -        }
 185.145 -        return modelClass.cast(data);
 185.146 -    }
 185.147 -
 185.148 -    @Override
 185.149 -    public Object toJSON(InputStream is) throws IOException {
 185.150 -        return LoadJSON.parse(is);
 185.151 -    }
 185.152 -
 185.153 -    @Override
 185.154 -    public void runSafe(final Runnable r) {
 185.155 -        class Wrap implements Runnable {
 185.156 -            @Override public void run() {
 185.157 -                try (Closeable c = Fn.activate(browserContext)) {
 185.158 -                    r.run();
 185.159 -                } catch (IOException ex) {
 185.160 -                    // cannot be thrown
 185.161 -                }
 185.162 -            }
 185.163 -        }
 185.164 -        Wrap w = new Wrap();
 185.165 -        
 185.166 -        if (Platform.isFxApplicationThread()) {
 185.167 -            w.run();
 185.168 -        } else {
 185.169 -            Platform.runLater(w);
 185.170 -        }
 185.171 -    }
 185.172 -
 185.173 -    @Override
 185.174 -    public LoadWS open(String url, JSONCall onReply) {
 185.175 -        return new LoadWS(onReply, url);
 185.176 -    }
 185.177 -
 185.178 -    @Override
 185.179 -    public void send(LoadWS socket, JSONCall data) {
 185.180 -        socket.send(data);
 185.181 -    }
 185.182 -
 185.183 -    @Override
 185.184 -    public void close(LoadWS socket) {
 185.185 -        socket.close();
 185.186 -    }
 185.187 -    
 185.188 -    @ServiceProvider(service = Contexts.Provider.class)
 185.189 -    public static final class Prvdr implements Contexts.Provider {
 185.190 -        @Override
 185.191 -        public void fillContext(Contexts.Builder context, Class<?> requestor) {
 185.192 -            if (isJavaScriptEnabled()) {
 185.193 -                FXContext c = new FXContext(Fn.activePresenter());
 185.194 -                
 185.195 -                context.register(Technology.class, c, 100);
 185.196 -                context.register(Transfer.class, c, 100);
 185.197 -                if (c.areWebSocketsSupported()) {
 185.198 -                    context.register(WSTransfer.class, c, 100);
 185.199 -                }
 185.200 -            }
 185.201 -        }
 185.202 -    }
 185.203 -}
   186.1 --- a/ko-fx/src/main/java/org/apidesign/html/kofx/Knockout.java	Thu Dec 19 17:11:01 2013 +0100
   186.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   186.3 @@ -1,123 +0,0 @@
   186.4 -/**
   186.5 - * HTML via Java(tm) Language Bindings
   186.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   186.7 - *
   186.8 - * This program is free software: you can redistribute it and/or modify
   186.9 - * it under the terms of the GNU General Public License as published by
  186.10 - * the Free Software Foundation, version 2 of the License.
  186.11 - *
  186.12 - * This program is distributed in the hope that it will be useful,
  186.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  186.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  186.15 - * GNU General Public License for more details. apidesign.org
  186.16 - * designates this particular file as subject to the
  186.17 - * "Classpath" exception as provided by apidesign.org
  186.18 - * in the License file that accompanied this code.
  186.19 - *
  186.20 - * You should have received a copy of the GNU General Public License
  186.21 - * along with this program. Look for COPYING file in the top folder.
  186.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  186.23 - */
  186.24 -package org.apidesign.html.kofx;
  186.25 -
  186.26 -import net.java.html.js.JavaScriptBody;
  186.27 -import net.java.html.js.JavaScriptResource;
  186.28 -import net.java.html.json.Model;
  186.29 -import netscape.javascript.JSObject;
  186.30 -import org.apidesign.html.json.spi.FunctionBinding;
  186.31 -import org.apidesign.html.json.spi.PropertyBinding;
  186.32 -
  186.33 -/** This is an implementation package - just
  186.34 - * include its JAR on classpath and use official {@link Context} API
  186.35 - * to access the functionality.
  186.36 - * <p>
  186.37 - * Provides binding between {@link Model models} and knockout.js running
  186.38 - * inside a JavaFX WebView. 
  186.39 - *
  186.40 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  186.41 - */
  186.42 -@JavaScriptResource("knockout-2.2.1.js")
  186.43 -final class Knockout {
  186.44 -    static final JSObject KObject;
  186.45 -    static {
  186.46 -        Console.register();
  186.47 -        KObject = (JSObject) kObj();
  186.48 -    }
  186.49 -
  186.50 -    static Object toArray(Object[] arr) {
  186.51 -        return KObject.call("array", arr);
  186.52 -    }
  186.53 -    
  186.54 -    @JavaScriptBody(args = { "model", "prop" }, body =
  186.55 -          "if (model) {\n"
  186.56 -        + "  var koProp = model[prop];\n"
  186.57 -        + "  if (koProp && koProp['valueHasMutated']) {\n"
  186.58 -        + "    koProp['valueHasMutated']();\n"
  186.59 -        + "  }\n"
  186.60 -        + "}\n"
  186.61 -    )
  186.62 -    public native static void valueHasMutated(JSObject model, String prop);
  186.63 -
  186.64 -    @JavaScriptBody(args = { "bindings" }, body = "ko.applyBindings(bindings);")
  186.65 -    native static void applyBindings(Object bindings);
  186.66 -    
  186.67 -    @JavaScriptBody(args = {}, body =
  186.68 -              "  var k = {};"
  186.69 -            + "  k.array= function() {"
  186.70 -            + "    return Array.prototype.slice.call(arguments);"
  186.71 -            + "  };"
  186.72 -            + "  return k;"
  186.73 -    )
  186.74 -    private static native Object kObj();
  186.75 -        
  186.76 -        
  186.77 -    @JavaScriptBody(
  186.78 -        javacall = true,
  186.79 -        args = {"model", "propNames", "propReadOnly", "propValues", "propArr", "funcNames", "funcArr"},
  186.80 -        body
  186.81 -        = "var ret = {};\n"
  186.82 -        + "ret['ko-fx.model'] = model;\n"
  186.83 -        + "function koComputed(name, readOnly, value, prop) {\n"
  186.84 -        + "  function realGetter() {\n"
  186.85 -        + "    try {"
  186.86 -        + "      var v = prop.@org.apidesign.html.json.spi.PropertyBinding::getValue()();"
  186.87 -        + "      return v;"
  186.88 -        + "    } catch (e) {"
  186.89 -        + "      alert(\"Cannot call getValue on \" + model + \" prop: \" + name + \" error: \" + e);"
  186.90 -        + "    }"
  186.91 -        + "  }\n"
  186.92 -        + "  var activeGetter = function() { return value; };\n"
  186.93 -        + "  var bnd = {"
  186.94 -        + "    read: function() {"
  186.95 -        + "      var r = activeGetter();"
  186.96 -        + "      activeGetter = realGetter;"
  186.97 -        + "      return r;"
  186.98 -        + "    },"
  186.99 -        + "    owner: ret\n"
 186.100 -        + "  };\n"
 186.101 -        + "  if (!readOnly) {\n"
 186.102 -        + "    bnd.write = function(val) {\n"
 186.103 -        + "      prop.@org.apidesign.html.json.spi.PropertyBinding::setValue(Ljava/lang/Object;)(val);\n"
 186.104 -        + "    };"
 186.105 -        + "  };"
 186.106 -        + "  ret[name] = ko.computed(bnd);"
 186.107 -        + "}\n"
 186.108 -        + "for (var i = 0; i < propNames.length; i++) {\n"
 186.109 -        + "  koComputed(propNames[i], propReadOnly[i], propValues[i], propArr[i]);\n"
 186.110 -        + "}\n"
 186.111 -        + "function koExpose(name, func) {\n"
 186.112 -        + "  ret[name] = function(data, ev) {\n"
 186.113 -        + "    func.@org.apidesign.html.json.spi.FunctionBinding::call(Ljava/lang/Object;Ljava/lang/Object;)(data, ev);\n"
 186.114 -        + "  };\n"
 186.115 -        + "}\n"
 186.116 -        + "for (var i = 0; i < funcNames.length; i++) {\n"
 186.117 -        + "  koExpose(funcNames[i], funcArr[i]);\n"
 186.118 -        + "}\n"
 186.119 -        + "return ret;\n"
 186.120 -        )
 186.121 -    static native JSObject wrapModel(
 186.122 -        Object model,
 186.123 -        String[] propNames, boolean[] propReadOnly, Object propValues, PropertyBinding[] propArr,
 186.124 -        String[] funcNames, FunctionBinding[] funcArr
 186.125 -    );
 186.126 -}
   187.1 --- a/ko-fx/src/main/java/org/apidesign/html/kofx/LoadJSON.java	Thu Dec 19 17:11:01 2013 +0100
   187.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   187.3 @@ -1,245 +0,0 @@
   187.4 -/**
   187.5 - * HTML via Java(tm) Language Bindings
   187.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   187.7 - *
   187.8 - * This program is free software: you can redistribute it and/or modify
   187.9 - * it under the terms of the GNU General Public License as published by
  187.10 - * the Free Software Foundation, version 2 of the License.
  187.11 - *
  187.12 - * This program is distributed in the hope that it will be useful,
  187.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  187.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  187.15 - * GNU General Public License for more details. apidesign.org
  187.16 - * designates this particular file as subject to the
  187.17 - * "Classpath" exception as provided by apidesign.org
  187.18 - * in the License file that accompanied this code.
  187.19 - *
  187.20 - * You should have received a copy of the GNU General Public License
  187.21 - * along with this program. Look for COPYING file in the top folder.
  187.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  187.23 - */
  187.24 -package org.apidesign.html.kofx;
  187.25 -
  187.26 -import java.io.IOException;
  187.27 -import java.io.InputStream;
  187.28 -import java.io.InputStreamReader;
  187.29 -import java.io.OutputStream;
  187.30 -import java.io.PushbackInputStream;
  187.31 -import java.io.Reader;
  187.32 -import java.net.HttpURLConnection;
  187.33 -import java.net.MalformedURLException;
  187.34 -import java.net.URL;
  187.35 -import java.net.URLConnection;
  187.36 -import java.util.Iterator;
  187.37 -import java.util.concurrent.Executor;
  187.38 -import java.util.concurrent.Executors;
  187.39 -import java.util.concurrent.ThreadFactory;
  187.40 -import java.util.logging.Level;
  187.41 -import java.util.logging.Logger;
  187.42 -import javafx.application.Platform;
  187.43 -import net.java.html.js.JavaScriptBody;
  187.44 -import netscape.javascript.JSObject;
  187.45 -import org.apidesign.html.json.spi.JSONCall;
  187.46 -import org.json.JSONArray;
  187.47 -import org.json.JSONException;
  187.48 -import org.json.JSONObject;
  187.49 -import org.json.JSONTokener;
  187.50 -
  187.51 -/** This is an implementation package - just
  187.52 - * include its JAR on classpath and use official {@link Context} API
  187.53 - * to access the functionality.
  187.54 - *
  187.55 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  187.56 - */
  187.57 -final class LoadJSON implements Runnable {
  187.58 -    private static final Logger LOG = FXContext.LOG;
  187.59 -    private static final Executor REQ = Executors.newCachedThreadPool(new ThreadFactory() {
  187.60 -        @Override
  187.61 -        public Thread newThread(Runnable runnable) {
  187.62 -            Thread thread = Executors.defaultThreadFactory().newThread(runnable);
  187.63 -            thread.setDaemon(true);
  187.64 -            return thread;
  187.65 -        }
  187.66 -    });
  187.67 -
  187.68 -    private final JSONCall call;
  187.69 -    private final URL base;
  187.70 -    private Throwable error;
  187.71 -    private Object json;
  187.72 -
  187.73 -
  187.74 -    private LoadJSON(JSONCall call) {
  187.75 -        this.call = call;
  187.76 -        URL b;
  187.77 -        try {
  187.78 -            b = new URL(findBaseURL());
  187.79 -        } catch (MalformedURLException ex) {
  187.80 -            LOG.log(Level.SEVERE, "Can't find base url for " + call.composeURL("dummy"), ex);
  187.81 -            b = null;
  187.82 -        }
  187.83 -        this.base = b;
  187.84 -    }
  187.85 -
  187.86 -    public static void loadJSON(JSONCall call) {
  187.87 -        assert !"WebSocket".equals(call.getMethod());
  187.88 -        REQ.execute(new LoadJSON((call)));
  187.89 -    }
  187.90 -
  187.91 -    @Override
  187.92 -    public void run() {
  187.93 -        if (Platform.isFxApplicationThread()) {
  187.94 -            if (error != null) {
  187.95 -                call.notifyError(error);
  187.96 -            } else {
  187.97 -                call.notifySuccess(json);
  187.98 -            }
  187.99 -            return;
 187.100 -        }
 187.101 -        final String url;
 187.102 -        if (call.isJSONP()) {
 187.103 -            url = call.composeURL("dummy");
 187.104 -        } else {
 187.105 -            url = call.composeURL(null);
 187.106 -        }
 187.107 -        try {
 187.108 -            final URL u = new URL(base, url.replace(" ", "%20"));
 187.109 -            URLConnection conn = u.openConnection();
 187.110 -            if (conn instanceof HttpURLConnection) {
 187.111 -                HttpURLConnection huc = (HttpURLConnection) conn;
 187.112 -                if (call.getMethod() != null) {
 187.113 -                    huc.setRequestMethod(call.getMethod());
 187.114 -                }
 187.115 -                if (call.isDoOutput()) {
 187.116 -                    huc.setDoOutput(true);
 187.117 -                    final OutputStream os = huc.getOutputStream();
 187.118 -                    call.writeData(os);
 187.119 -                    os.flush();
 187.120 -                }
 187.121 -            }
 187.122 -            final PushbackInputStream is = new PushbackInputStream(
 187.123 -                conn.getInputStream(), 1
 187.124 -            );
 187.125 -            boolean array = false;
 187.126 -            boolean string = false;
 187.127 -            if (call.isJSONP()) {
 187.128 -                for (;;) {
 187.129 -                    int ch = is.read();
 187.130 -                    if (ch == -1) {
 187.131 -                        break;
 187.132 -                    }
 187.133 -                    if (ch == '[') {
 187.134 -                        is.unread(ch);
 187.135 -                        array = true;
 187.136 -                        break;
 187.137 -                    }
 187.138 -                    if (ch == '{') {
 187.139 -                        is.unread(ch);
 187.140 -                        break;
 187.141 -                    }
 187.142 -                }
 187.143 -            } else {
 187.144 -                int ch = is.read();
 187.145 -                if (ch == -1) {
 187.146 -                    string = true;
 187.147 -                } else {
 187.148 -                    array = ch == '[';
 187.149 -                    is.unread(ch);
 187.150 -                    if (!array && ch != '{') {
 187.151 -                        string = true;
 187.152 -                    }
 187.153 -                }
 187.154 -            }
 187.155 -            try {
 187.156 -                if (string) {
 187.157 -                    throw new JSONException("");
 187.158 -                }
 187.159 -                Reader r = new InputStreamReader(is, "UTF-8");
 187.160 -
 187.161 -                JSONTokener tok = new JSONTokener(r);
 187.162 -                Object obj;
 187.163 -                obj = array ? new JSONArray(tok) : new JSONObject(tok);
 187.164 -                json = convertToArray(obj);
 187.165 -            } catch (JSONException ex) {
 187.166 -                Reader r = new InputStreamReader(is, "UTF-8");
 187.167 -                StringBuilder sb = new StringBuilder();
 187.168 -                for (;;) {
 187.169 -                    int ch = r.read();
 187.170 -                    if (ch == -1) {
 187.171 -                        break;
 187.172 -                    }
 187.173 -                    sb.append((char)ch);
 187.174 -                }
 187.175 -                json = sb.toString();
 187.176 -            }
 187.177 -        } catch (IOException ex) {
 187.178 -            error = ex;
 187.179 -        } finally {
 187.180 -            Platform.runLater(this);
 187.181 -        }
 187.182 -    }
 187.183 -
 187.184 -    static Object convertToArray(Object o) throws JSONException {
 187.185 -        if (o instanceof JSONArray) {
 187.186 -            JSONArray ja = (JSONArray)o;
 187.187 -            Object[] arr = new Object[ja.length()];
 187.188 -            for (int i = 0; i < arr.length; i++) {
 187.189 -                arr[i] = convertToArray(ja.get(i));
 187.190 -            }
 187.191 -            return arr;
 187.192 -        } else if (o instanceof JSONObject) {
 187.193 -            JSONObject obj = (JSONObject)o;
 187.194 -            Iterator it = obj.keys();
 187.195 -            while (it.hasNext()) {
 187.196 -                String key = (String)it.next();
 187.197 -                obj.put(key, convertToArray(obj.get(key)));
 187.198 -            }
 187.199 -            return obj;
 187.200 -        } else {
 187.201 -            return o;
 187.202 -        }
 187.203 -    }
 187.204 -    
 187.205 -    public static void extractJSON(Object jsonObject, String[] props, Object[] values) {
 187.206 -        if (jsonObject instanceof JSONObject) {
 187.207 -            JSONObject obj = (JSONObject)jsonObject;
 187.208 -            for (int i = 0; i < props.length; i++) {
 187.209 -                try {
 187.210 -                    values[i] = obj.has(props[i]) ? obj.get(props[i]) : null;
 187.211 -                } catch (JSONException ex) {
 187.212 -                    LoadJSON.LOG.log(Level.SEVERE, "Can't read " + props[i] + " from " + jsonObject, ex);
 187.213 -                }
 187.214 -            }
 187.215 -        }
 187.216 -        if (jsonObject instanceof JSObject) {
 187.217 -            JSObject obj = (JSObject)jsonObject;
 187.218 -            for (int i = 0; i < props.length; i++) {
 187.219 -                Object val = obj.getMember(props[i]);
 187.220 -                values[i] = isDefined(val) ? val : null;
 187.221 -            }
 187.222 -        }
 187.223 -    }
 187.224 -    
 187.225 -    public static Object parse(InputStream is) throws IOException {
 187.226 -        try {
 187.227 -            InputStreamReader r = new InputStreamReader(is, "UTF-8");
 187.228 -            JSONTokener t = new JSONTokener(r);
 187.229 -            return new JSONObject(t);
 187.230 -        } catch (JSONException ex) {
 187.231 -            throw new IOException(ex);
 187.232 -        }
 187.233 -    }
 187.234 -
 187.235 -    @JavaScriptBody(args = {  }, body = 
 187.236 -          "var h;"
 187.237 -        + "if (!!window && !!window.location && !!window.location.href)\n"
 187.238 -        + "  h = window.location.href;\n"
 187.239 -        + "else "
 187.240 -        + "  h = null;"
 187.241 -        + "return h;\n"
 187.242 -    )
 187.243 -    private static native String findBaseURL();
 187.244 -    
 187.245 -    private static boolean isDefined(Object val) {
 187.246 -        return !"undefined".equals(val);
 187.247 -    }
 187.248 -}
   188.1 --- a/ko-fx/src/main/java/org/apidesign/html/kofx/LoadWS.java	Thu Dec 19 17:11:01 2013 +0100
   188.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   188.3 @@ -1,127 +0,0 @@
   188.4 -/**
   188.5 - * HTML via Java(tm) Language Bindings
   188.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   188.7 - *
   188.8 - * This program is free software: you can redistribute it and/or modify
   188.9 - * it under the terms of the GNU General Public License as published by
  188.10 - * the Free Software Foundation, version 2 of the License.
  188.11 - *
  188.12 - * This program is distributed in the hope that it will be useful,
  188.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  188.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  188.15 - * GNU General Public License for more details. apidesign.org
  188.16 - * designates this particular file as subject to the
  188.17 - * "Classpath" exception as provided by apidesign.org
  188.18 - * in the License file that accompanied this code.
  188.19 - *
  188.20 - * You should have received a copy of the GNU General Public License
  188.21 - * along with this program. Look for COPYING file in the top folder.
  188.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  188.23 - */
  188.24 -package org.apidesign.html.kofx;
  188.25 -
  188.26 -import net.java.html.js.JavaScriptBody;
  188.27 -import org.apidesign.html.json.spi.JSONCall;
  188.28 -import org.json.JSONArray;
  188.29 -import org.json.JSONException;
  188.30 -import org.json.JSONObject;
  188.31 -import org.json.JSONTokener;
  188.32 -
  188.33 -/** Communication with WebSockets for WebView 1.8.
  188.34 - *
  188.35 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  188.36 - */
  188.37 -final class LoadWS {
  188.38 -    private static final boolean SUPPORTED = isWebSocket();
  188.39 -    private final Object ws;
  188.40 -    private final JSONCall call;
  188.41 -
  188.42 -    LoadWS(JSONCall first, String url) {
  188.43 -        call = first;
  188.44 -        ws = initWebSocket(this, url);
  188.45 -        if (ws == null) {
  188.46 -            first.notifyError(new IllegalArgumentException("Wrong URL: " + url));
  188.47 -        }
  188.48 -    }
  188.49 -    
  188.50 -    static boolean isSupported() {
  188.51 -        return SUPPORTED;
  188.52 -    }
  188.53 -    
  188.54 -    void send(JSONCall call) {
  188.55 -        push(call);
  188.56 -    }
  188.57 -    
  188.58 -    private synchronized void push(JSONCall call) {
  188.59 -        send(ws, call.getMessage());
  188.60 -    }
  188.61 -
  188.62 -    void onOpen(Object ev) {
  188.63 -        if (!call.isDoOutput()) {
  188.64 -            call.notifySuccess(null);
  188.65 -        }
  188.66 -    }
  188.67 -    
  188.68 -    void onMessage(Object ev, String data) {
  188.69 -        Object json;
  188.70 -        try {
  188.71 -            data = data.trim();
  188.72 -            
  188.73 -            JSONTokener tok = new JSONTokener(data);
  188.74 -            Object obj;
  188.75 -            obj = data.startsWith("[") ? new JSONArray(tok) : new JSONObject(tok);
  188.76 -            json = LoadJSON.convertToArray(obj);
  188.77 -        } catch (JSONException ex) {
  188.78 -            json = data;
  188.79 -        }
  188.80 -        call.notifySuccess(json);
  188.81 -    }
  188.82 -    
  188.83 -    void onError(Object ev) {
  188.84 -        call.notifyError(new Exception(ev.toString()));
  188.85 -    }
  188.86 -
  188.87 -    void onClose(boolean wasClean, int code, String reason) {
  188.88 -        call.notifyError(null);
  188.89 -    }
  188.90 -    
  188.91 -    @JavaScriptBody(args = {}, body = "if (window.WebSocket) return true; else return false;")
  188.92 -    private static boolean isWebSocket() {
  188.93 -        return false;
  188.94 -    }
  188.95 -
  188.96 -    @JavaScriptBody(args = { "back", "url" }, javacall = true, body = ""
  188.97 -        + "if (window.WebSocket) {"
  188.98 -        + "  try {"
  188.99 -        + "    var ws = new window.WebSocket(url);"
 188.100 -        + "    ws.onopen = function(ev) { back.@org.apidesign.html.kofx.LoadWS::onOpen(Ljava/lang/Object;)(ev); };"
 188.101 -        + "    ws.onmessage = function(ev) { back.@org.apidesign.html.kofx.LoadWS::onMessage(Ljava/lang/Object;Ljava/lang/String;)(ev, ev.data); };"
 188.102 -        + "    ws.onerror = function(ev) { back.@org.apidesign.html.kofx.LoadWS::onError(Ljava/lang/Object;)(ev); };"
 188.103 -        + "    ws.onclose = function(ev) { back.@org.apidesign.html.kofx.LoadWS::onClose(ZILjava/lang/String;)(ev.wasClean, ev.code, ev.reason); };"
 188.104 -        + "    return ws;"
 188.105 -        + "  } catch (ex) {"
 188.106 -        + "    return null;"
 188.107 -        + "  }"
 188.108 -        + "} else {"
 188.109 -        + "  return null;"
 188.110 -        + "}"
 188.111 -    )
 188.112 -    private static Object initWebSocket(Object back, String url) {
 188.113 -        return null;
 188.114 -    }
 188.115 -    
 188.116 -
 188.117 -    @JavaScriptBody(args = { "ws", "msg" }, body = ""
 188.118 -        + "ws.send(msg);"
 188.119 -    )
 188.120 -    private void send(Object ws, String msg) {
 188.121 -    }
 188.122 -
 188.123 -    @JavaScriptBody(args = { "ws" }, body = "ws.close();")
 188.124 -    private static void close(Object ws) {
 188.125 -    }
 188.126 -
 188.127 -    void close() {
 188.128 -        close(ws);
 188.129 -    }
 188.130 -}
   189.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   189.2 +++ b/ko-fx/src/main/java/org/netbeans/html/kofx/Console.java	Tue Jan 07 08:21:57 2014 +0100
   189.3 @@ -0,0 +1,81 @@
   189.4 +/**
   189.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   189.6 + *
   189.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   189.8 + *
   189.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  189.10 + * Other names may be trademarks of their respective owners.
  189.11 + *
  189.12 + * The contents of this file are subject to the terms of either the GNU
  189.13 + * General Public License Version 2 only ("GPL") or the Common
  189.14 + * Development and Distribution License("CDDL") (collectively, the
  189.15 + * "License"). You may not use this file except in compliance with the
  189.16 + * License. You can obtain a copy of the License at
  189.17 + * http://www.netbeans.org/cddl-gplv2.html
  189.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  189.19 + * specific language governing permissions and limitations under the
  189.20 + * License.  When distributing the software, include this License Header
  189.21 + * Notice in each file and include the License file at
  189.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  189.23 + * particular file as subject to the "Classpath" exception as provided
  189.24 + * by Oracle in the GPL Version 2 section of the License file that
  189.25 + * accompanied this code. If applicable, add the following below the
  189.26 + * License Header, with the fields enclosed by brackets [] replaced by
  189.27 + * your own identifying information:
  189.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  189.29 + *
  189.30 + * Contributor(s):
  189.31 + *
  189.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  189.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  189.34 + *
  189.35 + * If you wish your version of this file to be governed by only the CDDL
  189.36 + * or only the GPL Version 2, indicate your decision by adding
  189.37 + * "[Contributor] elects to include this software in this distribution
  189.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  189.39 + * single choice of license, a recipient has the option to distribute
  189.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  189.41 + * to extend the choice of license to its licensees as provided above.
  189.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  189.43 + * Version 2 license, then the option applies only if the new code is
  189.44 + * made subject to such option by the copyright holder.
  189.45 + */
  189.46 +package org.netbeans.html.kofx;
  189.47 +
  189.48 +import java.util.logging.Level;
  189.49 +import java.util.logging.Logger;
  189.50 +import net.java.html.js.JavaScriptBody;
  189.51 +
  189.52 +/** This is an implementation package - just
  189.53 + * include its JAR on classpath and use official {@link Context} API
  189.54 + * to access the functionality.
  189.55 + * <p>
  189.56 + * Redirects JavaScript's messages to Java's {@link Logger}.
  189.57 + *
  189.58 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  189.59 + */
  189.60 +final class Console {
  189.61 +    private static final Logger LOG = Logger.getLogger(Console.class.getName());
  189.62 +    
  189.63 +    private Console() {
  189.64 +    }
  189.65 +
  189.66 +    static void register() {
  189.67 +        registerImpl("log", Level.INFO);
  189.68 +        registerImpl("info", Level.INFO);
  189.69 +        registerImpl("warn", Level.WARNING);
  189.70 +        registerImpl("error", Level.SEVERE);
  189.71 +    }
  189.72 +    
  189.73 +    @JavaScriptBody(args = { "attr", "l" }, 
  189.74 +        javacall = true, body = 
  189.75 +        "  window.console[attr] = function(m) {\n"
  189.76 +      + "    @org.netbeans.html.kofx.Console::log(Ljava/util/logging/Level;Ljava/lang/String;)(l, m);\n"
  189.77 +      + "  };\n"
  189.78 +    )
  189.79 +    private static native void registerImpl(String attr, Level l);
  189.80 +    
  189.81 +    static void log(Level l, String msg) {
  189.82 +        LOG.log(l, msg);
  189.83 +    }
  189.84 +}
   190.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   190.2 +++ b/ko-fx/src/main/java/org/netbeans/html/kofx/FXContext.java	Tue Jan 07 08:21:57 2014 +0100
   190.3 @@ -0,0 +1,222 @@
   190.4 +/**
   190.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   190.6 + *
   190.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   190.8 + *
   190.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  190.10 + * Other names may be trademarks of their respective owners.
  190.11 + *
  190.12 + * The contents of this file are subject to the terms of either the GNU
  190.13 + * General Public License Version 2 only ("GPL") or the Common
  190.14 + * Development and Distribution License("CDDL") (collectively, the
  190.15 + * "License"). You may not use this file except in compliance with the
  190.16 + * License. You can obtain a copy of the License at
  190.17 + * http://www.netbeans.org/cddl-gplv2.html
  190.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  190.19 + * specific language governing permissions and limitations under the
  190.20 + * License.  When distributing the software, include this License Header
  190.21 + * Notice in each file and include the License file at
  190.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  190.23 + * particular file as subject to the "Classpath" exception as provided
  190.24 + * by Oracle in the GPL Version 2 section of the License file that
  190.25 + * accompanied this code. If applicable, add the following below the
  190.26 + * License Header, with the fields enclosed by brackets [] replaced by
  190.27 + * your own identifying information:
  190.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  190.29 + *
  190.30 + * Contributor(s):
  190.31 + *
  190.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  190.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  190.34 + *
  190.35 + * If you wish your version of this file to be governed by only the CDDL
  190.36 + * or only the GPL Version 2, indicate your decision by adding
  190.37 + * "[Contributor] elects to include this software in this distribution
  190.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  190.39 + * single choice of license, a recipient has the option to distribute
  190.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  190.41 + * to extend the choice of license to its licensees as provided above.
  190.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  190.43 + * Version 2 license, then the option applies only if the new code is
  190.44 + * made subject to such option by the copyright holder.
  190.45 + */
  190.46 +package org.netbeans.html.kofx;
  190.47 +
  190.48 +import java.io.Closeable;
  190.49 +import java.io.IOException;
  190.50 +import java.io.InputStream;
  190.51 +import java.util.ServiceLoader;
  190.52 +import java.util.logging.Logger;
  190.53 +import javafx.application.Platform;
  190.54 +import net.java.html.js.JavaScriptBody;
  190.55 +import netscape.javascript.JSObject;
  190.56 +import org.apidesign.html.boot.spi.Fn;
  190.57 +import org.apidesign.html.context.spi.Contexts;
  190.58 +import org.apidesign.html.json.spi.FunctionBinding;
  190.59 +import org.apidesign.html.json.spi.JSONCall;
  190.60 +import org.apidesign.html.json.spi.PropertyBinding;
  190.61 +import org.apidesign.html.json.spi.Technology;
  190.62 +import org.apidesign.html.json.spi.Transfer;
  190.63 +import org.apidesign.html.json.spi.WSTransfer;
  190.64 +import org.openide.util.lookup.ServiceProvider;
  190.65 +
  190.66 +/** This is an implementation package - just
  190.67 + * include its JAR on classpath and use official {@link Context} API
  190.68 + * to access the functionality.
  190.69 + * <p>
  190.70 + * Registers {@link ContextProvider}, so {@link ServiceLoader} can find it.
  190.71 + *
  190.72 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  190.73 + */
  190.74 +public final class FXContext
  190.75 +implements Technology.BatchInit<JSObject>, Transfer, WSTransfer<LoadWS> {
  190.76 +    static final Logger LOG = Logger.getLogger(FXContext.class.getName());
  190.77 +    private static Boolean javaScriptEnabled;
  190.78 +    private final Fn.Presenter browserContext;
  190.79 +
  190.80 +    public FXContext(Fn.Presenter browserContext) {
  190.81 +        this.browserContext = browserContext;
  190.82 +    }
  190.83 +    
  190.84 +    @JavaScriptBody(args = {}, body = "return true;")
  190.85 +    private static boolean isJavaScriptEnabledJs() {
  190.86 +        return false;
  190.87 +    }
  190.88 +    
  190.89 +    static boolean isJavaScriptEnabled() {
  190.90 +        if (javaScriptEnabled != null) {
  190.91 +            return javaScriptEnabled;
  190.92 +        }
  190.93 +        return javaScriptEnabled = isJavaScriptEnabledJs();
  190.94 +    }
  190.95 +
  190.96 +    final boolean areWebSocketsSupported() {
  190.97 +        return LoadWS.isSupported();
  190.98 +    }
  190.99 +
 190.100 +
 190.101 +    @Override
 190.102 +    public JSObject wrapModel(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
 190.103 +        String[] propNames = new String[propArr.length];
 190.104 +        boolean[] propReadOnly = new boolean[propArr.length];
 190.105 +        Object[] propValues = new Object[propArr.length];
 190.106 +        for (int i = 0; i < propNames.length; i++) {
 190.107 +            propNames[i] = propArr[i].getPropertyName();
 190.108 +            propReadOnly[i] = propArr[i].isReadOnly();
 190.109 +            propValues[i] = propArr[i].getValue();
 190.110 +        }
 190.111 +        String[] funcNames = new String[funcArr.length];
 190.112 +        for (int i = 0; i < funcNames.length; i++) {
 190.113 +            funcNames[i] = funcArr[i].getFunctionName();
 190.114 +        }
 190.115 +        
 190.116 +        return Knockout.wrapModel(model, 
 190.117 +            propNames, propReadOnly, Knockout.toArray(propValues), propArr, 
 190.118 +            funcNames, funcArr
 190.119 +        );
 190.120 +    }
 190.121 +    
 190.122 +    @Override
 190.123 +    public JSObject wrapModel(Object model) {
 190.124 +        throw new UnsupportedOperationException();
 190.125 +    }
 190.126 +
 190.127 +    @Override
 190.128 +    public void bind(PropertyBinding b, Object model, JSObject data) {
 190.129 +        throw new UnsupportedOperationException();
 190.130 +    }
 190.131 +
 190.132 +    @Override
 190.133 +    public void valueHasMutated(JSObject data, String propertyName) {
 190.134 +        Knockout.valueHasMutated(data, propertyName);
 190.135 +    }
 190.136 +
 190.137 +    @Override
 190.138 +    public void expose(FunctionBinding fb, Object model, JSObject d) {
 190.139 +        throw new UnsupportedOperationException();
 190.140 +    }
 190.141 +
 190.142 +    @Override
 190.143 +    public void applyBindings(JSObject data) {
 190.144 +        Knockout.applyBindings(data);
 190.145 +    }
 190.146 +
 190.147 +    @Override
 190.148 +    public Object wrapArray(Object[] arr) {
 190.149 +        return Knockout.toArray(arr);
 190.150 +    }
 190.151 +
 190.152 +    @Override
 190.153 +    public void extract(Object obj, String[] props, Object[] values) {
 190.154 +        LoadJSON.extractJSON(obj, props, values);
 190.155 +    }
 190.156 +
 190.157 +    @Override
 190.158 +    public void loadJSON(final JSONCall call) {
 190.159 +        LoadJSON.loadJSON(call);
 190.160 +    }
 190.161 +
 190.162 +    @Override
 190.163 +    public <M> M toModel(Class<M> modelClass, Object data) {
 190.164 +        if (data instanceof JSObject) {
 190.165 +            data = ((JSObject)data).getMember("ko-fx.model"); // NOI18N
 190.166 +        }
 190.167 +        return modelClass.cast(data);
 190.168 +    }
 190.169 +
 190.170 +    @Override
 190.171 +    public Object toJSON(InputStream is) throws IOException {
 190.172 +        return LoadJSON.parse(is);
 190.173 +    }
 190.174 +
 190.175 +    @Override
 190.176 +    public void runSafe(final Runnable r) {
 190.177 +        class Wrap implements Runnable {
 190.178 +            @Override public void run() {
 190.179 +                try (Closeable c = Fn.activate(browserContext)) {
 190.180 +                    r.run();
 190.181 +                } catch (IOException ex) {
 190.182 +                    // cannot be thrown
 190.183 +                }
 190.184 +            }
 190.185 +        }
 190.186 +        Wrap w = new Wrap();
 190.187 +        
 190.188 +        if (Platform.isFxApplicationThread()) {
 190.189 +            w.run();
 190.190 +        } else {
 190.191 +            Platform.runLater(w);
 190.192 +        }
 190.193 +    }
 190.194 +
 190.195 +    @Override
 190.196 +    public LoadWS open(String url, JSONCall onReply) {
 190.197 +        return new LoadWS(onReply, url);
 190.198 +    }
 190.199 +
 190.200 +    @Override
 190.201 +    public void send(LoadWS socket, JSONCall data) {
 190.202 +        socket.send(data);
 190.203 +    }
 190.204 +
 190.205 +    @Override
 190.206 +    public void close(LoadWS socket) {
 190.207 +        socket.close();
 190.208 +    }
 190.209 +    
 190.210 +    @ServiceProvider(service = Contexts.Provider.class)
 190.211 +    public static final class Prvdr implements Contexts.Provider {
 190.212 +        @Override
 190.213 +        public void fillContext(Contexts.Builder context, Class<?> requestor) {
 190.214 +            if (isJavaScriptEnabled()) {
 190.215 +                FXContext c = new FXContext(Fn.activePresenter());
 190.216 +                
 190.217 +                context.register(Technology.class, c, 100);
 190.218 +                context.register(Transfer.class, c, 100);
 190.219 +                if (c.areWebSocketsSupported()) {
 190.220 +                    context.register(WSTransfer.class, c, 100);
 190.221 +                }
 190.222 +            }
 190.223 +        }
 190.224 +    }
 190.225 +}
   191.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   191.2 +++ b/ko-fx/src/main/java/org/netbeans/html/kofx/Knockout.java	Tue Jan 07 08:21:57 2014 +0100
   191.3 @@ -0,0 +1,145 @@
   191.4 +/**
   191.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   191.6 + *
   191.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   191.8 + *
   191.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  191.10 + * Other names may be trademarks of their respective owners.
  191.11 + *
  191.12 + * The contents of this file are subject to the terms of either the GNU
  191.13 + * General Public License Version 2 only ("GPL") or the Common
  191.14 + * Development and Distribution License("CDDL") (collectively, the
  191.15 + * "License"). You may not use this file except in compliance with the
  191.16 + * License. You can obtain a copy of the License at
  191.17 + * http://www.netbeans.org/cddl-gplv2.html
  191.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  191.19 + * specific language governing permissions and limitations under the
  191.20 + * License.  When distributing the software, include this License Header
  191.21 + * Notice in each file and include the License file at
  191.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  191.23 + * particular file as subject to the "Classpath" exception as provided
  191.24 + * by Oracle in the GPL Version 2 section of the License file that
  191.25 + * accompanied this code. If applicable, add the following below the
  191.26 + * License Header, with the fields enclosed by brackets [] replaced by
  191.27 + * your own identifying information:
  191.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  191.29 + *
  191.30 + * Contributor(s):
  191.31 + *
  191.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  191.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  191.34 + *
  191.35 + * If you wish your version of this file to be governed by only the CDDL
  191.36 + * or only the GPL Version 2, indicate your decision by adding
  191.37 + * "[Contributor] elects to include this software in this distribution
  191.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  191.39 + * single choice of license, a recipient has the option to distribute
  191.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  191.41 + * to extend the choice of license to its licensees as provided above.
  191.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  191.43 + * Version 2 license, then the option applies only if the new code is
  191.44 + * made subject to such option by the copyright holder.
  191.45 + */
  191.46 +package org.netbeans.html.kofx;
  191.47 +
  191.48 +import net.java.html.js.JavaScriptBody;
  191.49 +import net.java.html.js.JavaScriptResource;
  191.50 +import net.java.html.json.Model;
  191.51 +import netscape.javascript.JSObject;
  191.52 +import org.apidesign.html.json.spi.FunctionBinding;
  191.53 +import org.apidesign.html.json.spi.PropertyBinding;
  191.54 +
  191.55 +/** This is an implementation package - just
  191.56 + * include its JAR on classpath and use official {@link Context} API
  191.57 + * to access the functionality.
  191.58 + * <p>
  191.59 + * Provides binding between {@link Model models} and knockout.js running
  191.60 + * inside a JavaFX WebView. 
  191.61 + *
  191.62 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  191.63 + */
  191.64 +@JavaScriptResource("knockout-2.2.1.js")
  191.65 +final class Knockout {
  191.66 +    static final JSObject KObject;
  191.67 +    static {
  191.68 +        Console.register();
  191.69 +        KObject = (JSObject) kObj();
  191.70 +    }
  191.71 +
  191.72 +    static Object toArray(Object[] arr) {
  191.73 +        return KObject.call("array", arr);
  191.74 +    }
  191.75 +    
  191.76 +    @JavaScriptBody(args = { "model", "prop" }, body =
  191.77 +          "if (model) {\n"
  191.78 +        + "  var koProp = model[prop];\n"
  191.79 +        + "  if (koProp && koProp['valueHasMutated']) {\n"
  191.80 +        + "    koProp['valueHasMutated']();\n"
  191.81 +        + "  }\n"
  191.82 +        + "}\n"
  191.83 +    )
  191.84 +    public native static void valueHasMutated(JSObject model, String prop);
  191.85 +
  191.86 +    @JavaScriptBody(args = { "bindings" }, body = "ko.applyBindings(bindings);")
  191.87 +    native static void applyBindings(Object bindings);
  191.88 +    
  191.89 +    @JavaScriptBody(args = {}, body =
  191.90 +              "  var k = {};"
  191.91 +            + "  k.array= function() {"
  191.92 +            + "    return Array.prototype.slice.call(arguments);"
  191.93 +            + "  };"
  191.94 +            + "  return k;"
  191.95 +    )
  191.96 +    private static native Object kObj();
  191.97 +        
  191.98 +        
  191.99 +    @JavaScriptBody(
 191.100 +        javacall = true,
 191.101 +        args = {"model", "propNames", "propReadOnly", "propValues", "propArr", "funcNames", "funcArr"},
 191.102 +        body
 191.103 +        = "var ret = {};\n"
 191.104 +        + "ret['ko-fx.model'] = model;\n"
 191.105 +        + "function koComputed(name, readOnly, value, prop) {\n"
 191.106 +        + "  function realGetter() {\n"
 191.107 +        + "    try {"
 191.108 +        + "      var v = prop.@org.apidesign.html.json.spi.PropertyBinding::getValue()();"
 191.109 +        + "      return v;"
 191.110 +        + "    } catch (e) {"
 191.111 +        + "      alert(\"Cannot call getValue on \" + model + \" prop: \" + name + \" error: \" + e);"
 191.112 +        + "    }"
 191.113 +        + "  }\n"
 191.114 +        + "  var activeGetter = function() { return value; };\n"
 191.115 +        + "  var bnd = {"
 191.116 +        + "    read: function() {"
 191.117 +        + "      var r = activeGetter();"
 191.118 +        + "      activeGetter = realGetter;"
 191.119 +        + "      return r;"
 191.120 +        + "    },"
 191.121 +        + "    owner: ret\n"
 191.122 +        + "  };\n"
 191.123 +        + "  if (!readOnly) {\n"
 191.124 +        + "    bnd.write = function(val) {\n"
 191.125 +        + "      prop.@org.apidesign.html.json.spi.PropertyBinding::setValue(Ljava/lang/Object;)(val);\n"
 191.126 +        + "    };"
 191.127 +        + "  };"
 191.128 +        + "  ret[name] = ko.computed(bnd);"
 191.129 +        + "}\n"
 191.130 +        + "for (var i = 0; i < propNames.length; i++) {\n"
 191.131 +        + "  koComputed(propNames[i], propReadOnly[i], propValues[i], propArr[i]);\n"
 191.132 +        + "}\n"
 191.133 +        + "function koExpose(name, func) {\n"
 191.134 +        + "  ret[name] = function(data, ev) {\n"
 191.135 +        + "    func.@org.apidesign.html.json.spi.FunctionBinding::call(Ljava/lang/Object;Ljava/lang/Object;)(data, ev);\n"
 191.136 +        + "  };\n"
 191.137 +        + "}\n"
 191.138 +        + "for (var i = 0; i < funcNames.length; i++) {\n"
 191.139 +        + "  koExpose(funcNames[i], funcArr[i]);\n"
 191.140 +        + "}\n"
 191.141 +        + "return ret;\n"
 191.142 +        )
 191.143 +    static native JSObject wrapModel(
 191.144 +        Object model,
 191.145 +        String[] propNames, boolean[] propReadOnly, Object propValues, PropertyBinding[] propArr,
 191.146 +        String[] funcNames, FunctionBinding[] funcArr
 191.147 +    );
 191.148 +}
   192.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   192.2 +++ b/ko-fx/src/main/java/org/netbeans/html/kofx/LoadJSON.java	Tue Jan 07 08:21:57 2014 +0100
   192.3 @@ -0,0 +1,267 @@
   192.4 +/**
   192.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   192.6 + *
   192.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   192.8 + *
   192.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  192.10 + * Other names may be trademarks of their respective owners.
  192.11 + *
  192.12 + * The contents of this file are subject to the terms of either the GNU
  192.13 + * General Public License Version 2 only ("GPL") or the Common
  192.14 + * Development and Distribution License("CDDL") (collectively, the
  192.15 + * "License"). You may not use this file except in compliance with the
  192.16 + * License. You can obtain a copy of the License at
  192.17 + * http://www.netbeans.org/cddl-gplv2.html
  192.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  192.19 + * specific language governing permissions and limitations under the
  192.20 + * License.  When distributing the software, include this License Header
  192.21 + * Notice in each file and include the License file at
  192.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  192.23 + * particular file as subject to the "Classpath" exception as provided
  192.24 + * by Oracle in the GPL Version 2 section of the License file that
  192.25 + * accompanied this code. If applicable, add the following below the
  192.26 + * License Header, with the fields enclosed by brackets [] replaced by
  192.27 + * your own identifying information:
  192.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  192.29 + *
  192.30 + * Contributor(s):
  192.31 + *
  192.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  192.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  192.34 + *
  192.35 + * If you wish your version of this file to be governed by only the CDDL
  192.36 + * or only the GPL Version 2, indicate your decision by adding
  192.37 + * "[Contributor] elects to include this software in this distribution
  192.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  192.39 + * single choice of license, a recipient has the option to distribute
  192.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  192.41 + * to extend the choice of license to its licensees as provided above.
  192.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  192.43 + * Version 2 license, then the option applies only if the new code is
  192.44 + * made subject to such option by the copyright holder.
  192.45 + */
  192.46 +package org.netbeans.html.kofx;
  192.47 +
  192.48 +import java.io.IOException;
  192.49 +import java.io.InputStream;
  192.50 +import java.io.InputStreamReader;
  192.51 +import java.io.OutputStream;
  192.52 +import java.io.PushbackInputStream;
  192.53 +import java.io.Reader;
  192.54 +import java.net.HttpURLConnection;
  192.55 +import java.net.MalformedURLException;
  192.56 +import java.net.URL;
  192.57 +import java.net.URLConnection;
  192.58 +import java.util.Iterator;
  192.59 +import java.util.concurrent.Executor;
  192.60 +import java.util.concurrent.Executors;
  192.61 +import java.util.concurrent.ThreadFactory;
  192.62 +import java.util.logging.Level;
  192.63 +import java.util.logging.Logger;
  192.64 +import javafx.application.Platform;
  192.65 +import net.java.html.js.JavaScriptBody;
  192.66 +import netscape.javascript.JSObject;
  192.67 +import org.apidesign.html.json.spi.JSONCall;
  192.68 +import org.json.JSONArray;
  192.69 +import org.json.JSONException;
  192.70 +import org.json.JSONObject;
  192.71 +import org.json.JSONTokener;
  192.72 +
  192.73 +/** This is an implementation package - just
  192.74 + * include its JAR on classpath and use official {@link Context} API
  192.75 + * to access the functionality.
  192.76 + *
  192.77 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  192.78 + */
  192.79 +final class LoadJSON implements Runnable {
  192.80 +    private static final Logger LOG = FXContext.LOG;
  192.81 +    private static final Executor REQ = Executors.newCachedThreadPool(new ThreadFactory() {
  192.82 +        @Override
  192.83 +        public Thread newThread(Runnable runnable) {
  192.84 +            Thread thread = Executors.defaultThreadFactory().newThread(runnable);
  192.85 +            thread.setDaemon(true);
  192.86 +            return thread;
  192.87 +        }
  192.88 +    });
  192.89 +
  192.90 +    private final JSONCall call;
  192.91 +    private final URL base;
  192.92 +    private Throwable error;
  192.93 +    private Object json;
  192.94 +
  192.95 +
  192.96 +    private LoadJSON(JSONCall call) {
  192.97 +        this.call = call;
  192.98 +        URL b;
  192.99 +        try {
 192.100 +            b = new URL(findBaseURL());
 192.101 +        } catch (MalformedURLException ex) {
 192.102 +            LOG.log(Level.SEVERE, "Can't find base url for " + call.composeURL("dummy"), ex);
 192.103 +            b = null;
 192.104 +        }
 192.105 +        this.base = b;
 192.106 +    }
 192.107 +
 192.108 +    public static void loadJSON(JSONCall call) {
 192.109 +        assert !"WebSocket".equals(call.getMethod());
 192.110 +        REQ.execute(new LoadJSON((call)));
 192.111 +    }
 192.112 +
 192.113 +    @Override
 192.114 +    public void run() {
 192.115 +        if (Platform.isFxApplicationThread()) {
 192.116 +            if (error != null) {
 192.117 +                call.notifyError(error);
 192.118 +            } else {
 192.119 +                call.notifySuccess(json);
 192.120 +            }
 192.121 +            return;
 192.122 +        }
 192.123 +        final String url;
 192.124 +        if (call.isJSONP()) {
 192.125 +            url = call.composeURL("dummy");
 192.126 +        } else {
 192.127 +            url = call.composeURL(null);
 192.128 +        }
 192.129 +        try {
 192.130 +            final URL u = new URL(base, url.replace(" ", "%20"));
 192.131 +            URLConnection conn = u.openConnection();
 192.132 +            if (conn instanceof HttpURLConnection) {
 192.133 +                HttpURLConnection huc = (HttpURLConnection) conn;
 192.134 +                if (call.getMethod() != null) {
 192.135 +                    huc.setRequestMethod(call.getMethod());
 192.136 +                }
 192.137 +                if (call.isDoOutput()) {
 192.138 +                    huc.setDoOutput(true);
 192.139 +                    final OutputStream os = huc.getOutputStream();
 192.140 +                    call.writeData(os);
 192.141 +                    os.flush();
 192.142 +                }
 192.143 +            }
 192.144 +            final PushbackInputStream is = new PushbackInputStream(
 192.145 +                conn.getInputStream(), 1
 192.146 +            );
 192.147 +            boolean array = false;
 192.148 +            boolean string = false;
 192.149 +            if (call.isJSONP()) {
 192.150 +                for (;;) {
 192.151 +                    int ch = is.read();
 192.152 +                    if (ch == -1) {
 192.153 +                        break;
 192.154 +                    }
 192.155 +                    if (ch == '[') {
 192.156 +                        is.unread(ch);
 192.157 +                        array = true;
 192.158 +                        break;
 192.159 +                    }
 192.160 +                    if (ch == '{') {
 192.161 +                        is.unread(ch);
 192.162 +                        break;
 192.163 +                    }
 192.164 +                }
 192.165 +            } else {
 192.166 +                int ch = is.read();
 192.167 +                if (ch == -1) {
 192.168 +                    string = true;
 192.169 +                } else {
 192.170 +                    array = ch == '[';
 192.171 +                    is.unread(ch);
 192.172 +                    if (!array && ch != '{') {
 192.173 +                        string = true;
 192.174 +                    }
 192.175 +                }
 192.176 +            }
 192.177 +            try {
 192.178 +                if (string) {
 192.179 +                    throw new JSONException("");
 192.180 +                }
 192.181 +                Reader r = new InputStreamReader(is, "UTF-8");
 192.182 +
 192.183 +                JSONTokener tok = new JSONTokener(r);
 192.184 +                Object obj;
 192.185 +                obj = array ? new JSONArray(tok) : new JSONObject(tok);
 192.186 +                json = convertToArray(obj);
 192.187 +            } catch (JSONException ex) {
 192.188 +                Reader r = new InputStreamReader(is, "UTF-8");
 192.189 +                StringBuilder sb = new StringBuilder();
 192.190 +                for (;;) {
 192.191 +                    int ch = r.read();
 192.192 +                    if (ch == -1) {
 192.193 +                        break;
 192.194 +                    }
 192.195 +                    sb.append((char)ch);
 192.196 +                }
 192.197 +                json = sb.toString();
 192.198 +            }
 192.199 +        } catch (IOException ex) {
 192.200 +            error = ex;
 192.201 +        } finally {
 192.202 +            Platform.runLater(this);
 192.203 +        }
 192.204 +    }
 192.205 +
 192.206 +    static Object convertToArray(Object o) throws JSONException {
 192.207 +        if (o instanceof JSONArray) {
 192.208 +            JSONArray ja = (JSONArray)o;
 192.209 +            Object[] arr = new Object[ja.length()];
 192.210 +            for (int i = 0; i < arr.length; i++) {
 192.211 +                arr[i] = convertToArray(ja.get(i));
 192.212 +            }
 192.213 +            return arr;
 192.214 +        } else if (o instanceof JSONObject) {
 192.215 +            JSONObject obj = (JSONObject)o;
 192.216 +            Iterator it = obj.keys();
 192.217 +            while (it.hasNext()) {
 192.218 +                String key = (String)it.next();
 192.219 +                obj.put(key, convertToArray(obj.get(key)));
 192.220 +            }
 192.221 +            return obj;
 192.222 +        } else {
 192.223 +            return o;
 192.224 +        }
 192.225 +    }
 192.226 +    
 192.227 +    public static void extractJSON(Object jsonObject, String[] props, Object[] values) {
 192.228 +        if (jsonObject instanceof JSONObject) {
 192.229 +            JSONObject obj = (JSONObject)jsonObject;
 192.230 +            for (int i = 0; i < props.length; i++) {
 192.231 +                try {
 192.232 +                    values[i] = obj.has(props[i]) ? obj.get(props[i]) : null;
 192.233 +                } catch (JSONException ex) {
 192.234 +                    LoadJSON.LOG.log(Level.SEVERE, "Can't read " + props[i] + " from " + jsonObject, ex);
 192.235 +                }
 192.236 +            }
 192.237 +        }
 192.238 +        if (jsonObject instanceof JSObject) {
 192.239 +            JSObject obj = (JSObject)jsonObject;
 192.240 +            for (int i = 0; i < props.length; i++) {
 192.241 +                Object val = obj.getMember(props[i]);
 192.242 +                values[i] = isDefined(val) ? val : null;
 192.243 +            }
 192.244 +        }
 192.245 +    }
 192.246 +    
 192.247 +    public static Object parse(InputStream is) throws IOException {
 192.248 +        try {
 192.249 +            InputStreamReader r = new InputStreamReader(is, "UTF-8");
 192.250 +            JSONTokener t = new JSONTokener(r);
 192.251 +            return new JSONObject(t);
 192.252 +        } catch (JSONException ex) {
 192.253 +            throw new IOException(ex);
 192.254 +        }
 192.255 +    }
 192.256 +
 192.257 +    @JavaScriptBody(args = {  }, body = 
 192.258 +          "var h;"
 192.259 +        + "if (!!window && !!window.location && !!window.location.href)\n"
 192.260 +        + "  h = window.location.href;\n"
 192.261 +        + "else "
 192.262 +        + "  h = null;"
 192.263 +        + "return h;\n"
 192.264 +    )
 192.265 +    private static native String findBaseURL();
 192.266 +    
 192.267 +    private static boolean isDefined(Object val) {
 192.268 +        return !"undefined".equals(val);
 192.269 +    }
 192.270 +}
   193.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   193.2 +++ b/ko-fx/src/main/java/org/netbeans/html/kofx/LoadWS.java	Tue Jan 07 08:21:57 2014 +0100
   193.3 @@ -0,0 +1,149 @@
   193.4 +/**
   193.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   193.6 + *
   193.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   193.8 + *
   193.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  193.10 + * Other names may be trademarks of their respective owners.
  193.11 + *
  193.12 + * The contents of this file are subject to the terms of either the GNU
  193.13 + * General Public License Version 2 only ("GPL") or the Common
  193.14 + * Development and Distribution License("CDDL") (collectively, the
  193.15 + * "License"). You may not use this file except in compliance with the
  193.16 + * License. You can obtain a copy of the License at
  193.17 + * http://www.netbeans.org/cddl-gplv2.html
  193.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  193.19 + * specific language governing permissions and limitations under the
  193.20 + * License.  When distributing the software, include this License Header
  193.21 + * Notice in each file and include the License file at
  193.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  193.23 + * particular file as subject to the "Classpath" exception as provided
  193.24 + * by Oracle in the GPL Version 2 section of the License file that
  193.25 + * accompanied this code. If applicable, add the following below the
  193.26 + * License Header, with the fields enclosed by brackets [] replaced by
  193.27 + * your own identifying information:
  193.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  193.29 + *
  193.30 + * Contributor(s):
  193.31 + *
  193.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  193.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  193.34 + *
  193.35 + * If you wish your version of this file to be governed by only the CDDL
  193.36 + * or only the GPL Version 2, indicate your decision by adding
  193.37 + * "[Contributor] elects to include this software in this distribution
  193.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  193.39 + * single choice of license, a recipient has the option to distribute
  193.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  193.41 + * to extend the choice of license to its licensees as provided above.
  193.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  193.43 + * Version 2 license, then the option applies only if the new code is
  193.44 + * made subject to such option by the copyright holder.
  193.45 + */
  193.46 +package org.netbeans.html.kofx;
  193.47 +
  193.48 +import net.java.html.js.JavaScriptBody;
  193.49 +import org.apidesign.html.json.spi.JSONCall;
  193.50 +import org.json.JSONArray;
  193.51 +import org.json.JSONException;
  193.52 +import org.json.JSONObject;
  193.53 +import org.json.JSONTokener;
  193.54 +
  193.55 +/** Communication with WebSockets for WebView 1.8.
  193.56 + *
  193.57 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  193.58 + */
  193.59 +final class LoadWS {
  193.60 +    private static final boolean SUPPORTED = isWebSocket();
  193.61 +    private final Object ws;
  193.62 +    private final JSONCall call;
  193.63 +
  193.64 +    LoadWS(JSONCall first, String url) {
  193.65 +        call = first;
  193.66 +        ws = initWebSocket(this, url);
  193.67 +        if (ws == null) {
  193.68 +            first.notifyError(new IllegalArgumentException("Wrong URL: " + url));
  193.69 +        }
  193.70 +    }
  193.71 +    
  193.72 +    static boolean isSupported() {
  193.73 +        return SUPPORTED;
  193.74 +    }
  193.75 +    
  193.76 +    void send(JSONCall call) {
  193.77 +        push(call);
  193.78 +    }
  193.79 +    
  193.80 +    private synchronized void push(JSONCall call) {
  193.81 +        send(ws, call.getMessage());
  193.82 +    }
  193.83 +
  193.84 +    void onOpen(Object ev) {
  193.85 +        if (!call.isDoOutput()) {
  193.86 +            call.notifySuccess(null);
  193.87 +        }
  193.88 +    }
  193.89 +    
  193.90 +    void onMessage(Object ev, String data) {
  193.91 +        Object json;
  193.92 +        try {
  193.93 +            data = data.trim();
  193.94 +            
  193.95 +            JSONTokener tok = new JSONTokener(data);
  193.96 +            Object obj;
  193.97 +            obj = data.startsWith("[") ? new JSONArray(tok) : new JSONObject(tok);
  193.98 +            json = LoadJSON.convertToArray(obj);
  193.99 +        } catch (JSONException ex) {
 193.100 +            json = data;
 193.101 +        }
 193.102 +        call.notifySuccess(json);
 193.103 +    }
 193.104 +    
 193.105 +    void onError(Object ev) {
 193.106 +        call.notifyError(new Exception(ev.toString()));
 193.107 +    }
 193.108 +
 193.109 +    void onClose(boolean wasClean, int code, String reason) {
 193.110 +        call.notifyError(null);
 193.111 +    }
 193.112 +    
 193.113 +    @JavaScriptBody(args = {}, body = "if (window.WebSocket) return true; else return false;")
 193.114 +    private static boolean isWebSocket() {
 193.115 +        return false;
 193.116 +    }
 193.117 +
 193.118 +    @JavaScriptBody(args = { "back", "url" }, javacall = true, body = ""
 193.119 +        + "if (window.WebSocket) {"
 193.120 +        + "  try {"
 193.121 +        + "    var ws = new window.WebSocket(url);"
 193.122 +        + "    ws.onopen = function(ev) { back.@org.netbeans.html.kofx.LoadWS::onOpen(Ljava/lang/Object;)(ev); };"
 193.123 +        + "    ws.onmessage = function(ev) { back.@org.netbeans.html.kofx.LoadWS::onMessage(Ljava/lang/Object;Ljava/lang/String;)(ev, ev.data); };"
 193.124 +        + "    ws.onerror = function(ev) { back.@org.netbeans.html.kofx.LoadWS::onError(Ljava/lang/Object;)(ev); };"
 193.125 +        + "    ws.onclose = function(ev) { back.@org.netbeans.html.kofx.LoadWS::onClose(ZILjava/lang/String;)(ev.wasClean, ev.code, ev.reason); };"
 193.126 +        + "    return ws;"
 193.127 +        + "  } catch (ex) {"
 193.128 +        + "    return null;"
 193.129 +        + "  }"
 193.130 +        + "} else {"
 193.131 +        + "  return null;"
 193.132 +        + "}"
 193.133 +    )
 193.134 +    private static Object initWebSocket(Object back, String url) {
 193.135 +        return null;
 193.136 +    }
 193.137 +    
 193.138 +
 193.139 +    @JavaScriptBody(args = { "ws", "msg" }, body = ""
 193.140 +        + "ws.send(msg);"
 193.141 +    )
 193.142 +    private void send(Object ws, String msg) {
 193.143 +    }
 193.144 +
 193.145 +    @JavaScriptBody(args = { "ws" }, body = "ws.close();")
 193.146 +    private static void close(Object ws) {
 193.147 +    }
 193.148 +
 193.149 +    void close() {
 193.150 +        close(ws);
 193.151 +    }
 193.152 +}
   194.1 --- a/ko-fx/src/main/resources/org/apidesign/html/kofx/knockout-2.2.1.js	Thu Dec 19 17:11:01 2013 +0100
   194.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   194.3 @@ -1,3594 +0,0 @@
   194.4 -// Knockout JavaScript library v2.2.1
   194.5 -// (c) Steven Sanderson - http://knockoutjs.com/
   194.6 -// License: MIT (http://www.opensource.org/licenses/mit-license.php)
   194.7 -
   194.8 -(function(){
   194.9 -var DEBUG=true;
  194.10 -(function(window,document,navigator,jQuery,undefined){
  194.11 -!function(factory) {
  194.12 -    // Support three module loading scenarios
  194.13 -    if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
  194.14 -        // [1] CommonJS/Node.js
  194.15 -        var target = module['exports'] || exports; // module.exports is for Node.js
  194.16 -        factory(target);
  194.17 -    } else if (typeof define === 'function' && define['amd']) {
  194.18 -        // [2] AMD anonymous module
  194.19 -        define(['exports'], factory);
  194.20 -    } else {
  194.21 -        // [3] No module loader (plain <script> tag) - put directly in global namespace
  194.22 -        factory(window['ko'] = {});
  194.23 -    }
  194.24 -}(function(koExports){
  194.25 -// Internally, all KO objects are attached to koExports (even the non-exported ones whose names will be minified by the closure compiler).
  194.26 -// In the future, the following "ko" variable may be made distinct from "koExports" so that private objects are not externally reachable.
  194.27 -var ko = typeof koExports !== 'undefined' ? koExports : {};
  194.28 -// Google Closure Compiler helpers (used only to make the minified file smaller)
  194.29 -ko.exportSymbol = function(koPath, object) {
  194.30 -	var tokens = koPath.split(".");
  194.31 -
  194.32 -	// In the future, "ko" may become distinct from "koExports" (so that non-exported objects are not reachable)
  194.33 -	// At that point, "target" would be set to: (typeof koExports !== "undefined" ? koExports : ko)
  194.34 -	var target = ko;
  194.35 -
  194.36 -	for (var i = 0; i < tokens.length - 1; i++)
  194.37 -		target = target[tokens[i]];
  194.38 -	target[tokens[tokens.length - 1]] = object;
  194.39 -};
  194.40 -ko.exportProperty = function(owner, publicName, object) {
  194.41 -  owner[publicName] = object;
  194.42 -};
  194.43 -ko.version = "2.2.1";
  194.44 -
  194.45 -ko.exportSymbol('version', ko.version);
  194.46 -ko.utils = new (function () {
  194.47 -    var stringTrimRegex = /^(\s|\u00A0)+|(\s|\u00A0)+$/g;
  194.48 -
  194.49 -    // Represent the known event types in a compact way, then at runtime transform it into a hash with event name as key (for fast lookup)
  194.50 -    var knownEvents = {}, knownEventTypesByEventName = {};
  194.51 -    var keyEventTypeName = /Firefox\/2/i.test(navigator.userAgent) ? 'KeyboardEvent' : 'UIEvents';
  194.52 -    knownEvents[keyEventTypeName] = ['keyup', 'keydown', 'keypress'];
  194.53 -    knownEvents['MouseEvents'] = ['click', 'dblclick', 'mousedown', 'mouseup', 'mousemove', 'mouseover', 'mouseout', 'mouseenter', 'mouseleave'];
  194.54 -    for (var eventType in knownEvents) {
  194.55 -        var knownEventsForType = knownEvents[eventType];
  194.56 -        if (knownEventsForType.length) {
  194.57 -            for (var i = 0, j = knownEventsForType.length; i < j; i++)
  194.58 -                knownEventTypesByEventName[knownEventsForType[i]] = eventType;
  194.59 -        }
  194.60 -    }
  194.61 -    var eventsThatMustBeRegisteredUsingAttachEvent = { 'propertychange': true }; // Workaround for an IE9 issue - https://github.com/SteveSanderson/knockout/issues/406
  194.62 -
  194.63 -    // Detect IE versions for bug workarounds (uses IE conditionals, not UA string, for robustness)
  194.64 -    // Note that, since IE 10 does not support conditional comments, the following logic only detects IE < 10.
  194.65 -    // Currently this is by design, since IE 10+ behaves correctly when treated as a standard browser.
  194.66 -    // If there is a future need to detect specific versions of IE10+, we will amend this.
  194.67 -    var ieVersion = (function() {
  194.68 -        var version = 3, div = document.createElement('div'), iElems = div.getElementsByTagName('i');
  194.69 -
  194.70 -        // Keep constructing conditional HTML blocks until we hit one that resolves to an empty fragment
  194.71 -        while (
  194.72 -            div.innerHTML = '<!--[if gt IE ' + (++version) + ']><i></i><![endif]-->',
  194.73 -            iElems[0]
  194.74 -        );
  194.75 -        return version > 4 ? version : undefined;
  194.76 -    }());
  194.77 -    var isIe6 = ieVersion === 6,
  194.78 -        isIe7 = ieVersion === 7;
  194.79 -
  194.80 -    function isClickOnCheckableElement(element, eventType) {
  194.81 -        if ((ko.utils.tagNameLower(element) !== "input") || !element.type) return false;
  194.82 -        if (eventType.toLowerCase() != "click") return false;
  194.83 -        var inputType = element.type;
  194.84 -        return (inputType == "checkbox") || (inputType == "radio");
  194.85 -    }
  194.86 -
  194.87 -    return {
  194.88 -        fieldsIncludedWithJsonPost: ['authenticity_token', /^__RequestVerificationToken(_.*)?$/],
  194.89 -
  194.90 -        arrayForEach: function (array, action) {
  194.91 -            for (var i = 0, j = array.length; i < j; i++)
  194.92 -                action(array[i]);
  194.93 -        },
  194.94 -
  194.95 -        arrayIndexOf: function (array, item) {
  194.96 -            if (typeof Array.prototype.indexOf == "function")
  194.97 -                return Array.prototype.indexOf.call(array, item);
  194.98 -            for (var i = 0, j = array.length; i < j; i++)
  194.99 -                if (array[i] === item)
 194.100 -                    return i;
 194.101 -            return -1;
 194.102 -        },
 194.103 -
 194.104 -        arrayFirst: function (array, predicate, predicateOwner) {
 194.105 -            for (var i = 0, j = array.length; i < j; i++)
 194.106 -                if (predicate.call(predicateOwner, array[i]))
 194.107 -                    return array[i];
 194.108 -            return null;
 194.109 -        },
 194.110 -
 194.111 -        arrayRemoveItem: function (array, itemToRemove) {
 194.112 -            var index = ko.utils.arrayIndexOf(array, itemToRemove);
 194.113 -            if (index >= 0)
 194.114 -                array.splice(index, 1);
 194.115 -        },
 194.116 -
 194.117 -        arrayGetDistinctValues: function (array) {
 194.118 -            array = array || [];
 194.119 -            var result = [];
 194.120 -            for (var i = 0, j = array.length; i < j; i++) {
 194.121 -                if (ko.utils.arrayIndexOf(result, array[i]) < 0)
 194.122 -                    result.push(array[i]);
 194.123 -            }
 194.124 -            return result;
 194.125 -        },
 194.126 -
 194.127 -        arrayMap: function (array, mapping) {
 194.128 -            array = array || [];
 194.129 -            var result = [];
 194.130 -            for (var i = 0, j = array.length; i < j; i++)
 194.131 -                result.push(mapping(array[i]));
 194.132 -            return result;
 194.133 -        },
 194.134 -
 194.135 -        arrayFilter: function (array, predicate) {
 194.136 -            array = array || [];
 194.137 -            var result = [];
 194.138 -            for (var i = 0, j = array.length; i < j; i++)
 194.139 -                if (predicate(array[i]))
 194.140 -                    result.push(array[i]);
 194.141 -            return result;
 194.142 -        },
 194.143 -
 194.144 -        arrayPushAll: function (array, valuesToPush) {
 194.145 -            if (valuesToPush instanceof Array)
 194.146 -                array.push.apply(array, valuesToPush);
 194.147 -            else
 194.148 -                for (var i = 0, j = valuesToPush.length; i < j; i++)
 194.149 -                    array.push(valuesToPush[i]);
 194.150 -            return array;
 194.151 -        },
 194.152 -
 194.153 -        extend: function (target, source) {
 194.154 -            if (source) {
 194.155 -                for(var prop in source) {
 194.156 -                    if(source.hasOwnProperty(prop)) {
 194.157 -                        target[prop] = source[prop];
 194.158 -                    }
 194.159 -                }
 194.160 -            }
 194.161 -            return target;
 194.162 -        },
 194.163 -
 194.164 -        emptyDomNode: function (domNode) {
 194.165 -            while (domNode.firstChild) {
 194.166 -                ko.removeNode(domNode.firstChild);
 194.167 -            }
 194.168 -        },
 194.169 -
 194.170 -        moveCleanedNodesToContainerElement: function(nodes) {
 194.171 -            // Ensure it's a real array, as we're about to reparent the nodes and
 194.172 -            // we don't want the underlying collection to change while we're doing that.
 194.173 -            var nodesArray = ko.utils.makeArray(nodes);
 194.174 -
 194.175 -            var container = document.createElement('div');
 194.176 -            for (var i = 0, j = nodesArray.length; i < j; i++) {
 194.177 -                container.appendChild(ko.cleanNode(nodesArray[i]));
 194.178 -            }
 194.179 -            return container;
 194.180 -        },
 194.181 -
 194.182 -        cloneNodes: function (nodesArray, shouldCleanNodes) {
 194.183 -            for (var i = 0, j = nodesArray.length, newNodesArray = []; i < j; i++) {
 194.184 -                var clonedNode = nodesArray[i].cloneNode(true);
 194.185 -                newNodesArray.push(shouldCleanNodes ? ko.cleanNode(clonedNode) : clonedNode);
 194.186 -            }
 194.187 -            return newNodesArray;
 194.188 -        },
 194.189 -
 194.190 -        setDomNodeChildren: function (domNode, childNodes) {
 194.191 -            ko.utils.emptyDomNode(domNode);
 194.192 -            if (childNodes) {
 194.193 -                for (var i = 0, j = childNodes.length; i < j; i++)
 194.194 -                    domNode.appendChild(childNodes[i]);
 194.195 -            }
 194.196 -        },
 194.197 -
 194.198 -        replaceDomNodes: function (nodeToReplaceOrNodeArray, newNodesArray) {
 194.199 -            var nodesToReplaceArray = nodeToReplaceOrNodeArray.nodeType ? [nodeToReplaceOrNodeArray] : nodeToReplaceOrNodeArray;
 194.200 -            if (nodesToReplaceArray.length > 0) {
 194.201 -                var insertionPoint = nodesToReplaceArray[0];
 194.202 -                var parent = insertionPoint.parentNode;
 194.203 -                for (var i = 0, j = newNodesArray.length; i < j; i++)
 194.204 -                    parent.insertBefore(newNodesArray[i], insertionPoint);
 194.205 -                for (var i = 0, j = nodesToReplaceArray.length; i < j; i++) {
 194.206 -                    ko.removeNode(nodesToReplaceArray[i]);
 194.207 -                }
 194.208 -            }
 194.209 -        },
 194.210 -
 194.211 -        setOptionNodeSelectionState: function (optionNode, isSelected) {
 194.212 -            // IE6 sometimes throws "unknown error" if you try to write to .selected directly, whereas Firefox struggles with setAttribute. Pick one based on browser.
 194.213 -            if (ieVersion < 7)
 194.214 -                optionNode.setAttribute("selected", isSelected);
 194.215 -            else
 194.216 -                optionNode.selected = isSelected;
 194.217 -        },
 194.218 -
 194.219 -        stringTrim: function (string) {
 194.220 -            return (string || "").replace(stringTrimRegex, "");
 194.221 -        },
 194.222 -
 194.223 -        stringTokenize: function (string, delimiter) {
 194.224 -            var result = [];
 194.225 -            var tokens = (string || "").split(delimiter);
 194.226 -            for (var i = 0, j = tokens.length; i < j; i++) {
 194.227 -                var trimmed = ko.utils.stringTrim(tokens[i]);
 194.228 -                if (trimmed !== "")
 194.229 -                    result.push(trimmed);
 194.230 -            }
 194.231 -            return result;
 194.232 -        },
 194.233 -
 194.234 -        stringStartsWith: function (string, startsWith) {
 194.235 -            string = string || "";
 194.236 -            if (startsWith.length > string.length)
 194.237 -                return false;
 194.238 -            return string.substring(0, startsWith.length) === startsWith;
 194.239 -        },
 194.240 -
 194.241 -        domNodeIsContainedBy: function (node, containedByNode) {
 194.242 -            if (containedByNode.compareDocumentPosition)
 194.243 -                return (containedByNode.compareDocumentPosition(node) & 16) == 16;
 194.244 -            while (node != null) {
 194.245 -                if (node == containedByNode)
 194.246 -                    return true;
 194.247 -                node = node.parentNode;
 194.248 -            }
 194.249 -            return false;
 194.250 -        },
 194.251 -
 194.252 -        domNodeIsAttachedToDocument: function (node) {
 194.253 -            return ko.utils.domNodeIsContainedBy(node, node.ownerDocument);
 194.254 -        },
 194.255 -
 194.256 -        tagNameLower: function(element) {
 194.257 -            // For HTML elements, tagName will always be upper case; for XHTML elements, it'll be lower case.
 194.258 -            // Possible future optimization: If we know it's an element from an XHTML document (not HTML),
 194.259 -            // we don't need to do the .toLowerCase() as it will always be lower case anyway.
 194.260 -            return element && element.tagName && element.tagName.toLowerCase();
 194.261 -        },
 194.262 -
 194.263 -        registerEventHandler: function (element, eventType, handler) {
 194.264 -            var mustUseAttachEvent = ieVersion && eventsThatMustBeRegisteredUsingAttachEvent[eventType];
 194.265 -            if (!mustUseAttachEvent && typeof jQuery != "undefined") {
 194.266 -                if (isClickOnCheckableElement(element, eventType)) {
 194.267 -                    // For click events on checkboxes, jQuery interferes with the event handling in an awkward way:
 194.268 -                    // it toggles the element checked state *after* the click event handlers run, whereas native
 194.269 -                    // click events toggle the checked state *before* the event handler.
 194.270 -                    // Fix this by intecepting the handler and applying the correct checkedness before it runs.
 194.271 -                    var originalHandler = handler;
 194.272 -                    handler = function(event, eventData) {
 194.273 -                        var jQuerySuppliedCheckedState = this.checked;
 194.274 -                        if (eventData)
 194.275 -                            this.checked = eventData.checkedStateBeforeEvent !== true;
 194.276 -                        originalHandler.call(this, event);
 194.277 -                        this.checked = jQuerySuppliedCheckedState; // Restore the state jQuery applied
 194.278 -                    };
 194.279 -                }
 194.280 -                jQuery(element)['bind'](eventType, handler);
 194.281 -            } else if (!mustUseAttachEvent && typeof element.addEventListener == "function")
 194.282 -                element.addEventListener(eventType, handler, false);
 194.283 -            else if (typeof element.attachEvent != "undefined")
 194.284 -                element.attachEvent("on" + eventType, function (event) {
 194.285 -                    handler.call(element, event);
 194.286 -                });
 194.287 -            else
 194.288 -                throw new Error("Browser doesn't support addEventListener or attachEvent");
 194.289 -        },
 194.290 -
 194.291 -        triggerEvent: function (element, eventType) {
 194.292 -            if (!(element && element.nodeType))
 194.293 -                throw new Error("element must be a DOM node when calling triggerEvent");
 194.294 -
 194.295 -            if (typeof jQuery != "undefined") {
 194.296 -                var eventData = [];
 194.297 -                if (isClickOnCheckableElement(element, eventType)) {
 194.298 -                    // Work around the jQuery "click events on checkboxes" issue described above by storing the original checked state before triggering the handler
 194.299 -                    eventData.push({ checkedStateBeforeEvent: element.checked });
 194.300 -                }
 194.301 -                jQuery(element)['trigger'](eventType, eventData);
 194.302 -            } else if (typeof document.createEvent == "function") {
 194.303 -                if (typeof element.dispatchEvent == "function") {
 194.304 -                    var eventCategory = knownEventTypesByEventName[eventType] || "HTMLEvents";
 194.305 -                    var event = document.createEvent(eventCategory);
 194.306 -                    event.initEvent(eventType, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, element);
 194.307 -                    element.dispatchEvent(event);
 194.308 -                }
 194.309 -                else
 194.310 -                    throw new Error("The supplied element doesn't support dispatchEvent");
 194.311 -            } else if (typeof element.fireEvent != "undefined") {
 194.312 -                // Unlike other browsers, IE doesn't change the checked state of checkboxes/radiobuttons when you trigger their "click" event
 194.313 -                // so to make it consistent, we'll do it manually here
 194.314 -                if (isClickOnCheckableElement(element, eventType))
 194.315 -                    element.checked = element.checked !== true;
 194.316 -                element.fireEvent("on" + eventType);
 194.317 -            }
 194.318 -            else
 194.319 -                throw new Error("Browser doesn't support triggering events");
 194.320 -        },
 194.321 -
 194.322 -        unwrapObservable: function (value) {
 194.323 -            return ko.isObservable(value) ? value() : value;
 194.324 -        },
 194.325 -
 194.326 -        peekObservable: function (value) {
 194.327 -            return ko.isObservable(value) ? value.peek() : value;
 194.328 -        },
 194.329 -
 194.330 -        toggleDomNodeCssClass: function (node, classNames, shouldHaveClass) {
 194.331 -            if (classNames) {
 194.332 -                var cssClassNameRegex = /[\w-]+/g,
 194.333 -                    currentClassNames = node.className.match(cssClassNameRegex) || [];
 194.334 -                ko.utils.arrayForEach(classNames.match(cssClassNameRegex), function(className) {
 194.335 -                    var indexOfClass = ko.utils.arrayIndexOf(currentClassNames, className);
 194.336 -                    if (indexOfClass >= 0) {
 194.337 -                        if (!shouldHaveClass)
 194.338 -                            currentClassNames.splice(indexOfClass, 1);
 194.339 -                    } else {
 194.340 -                        if (shouldHaveClass)
 194.341 -                            currentClassNames.push(className);
 194.342 -                    }
 194.343 -                });
 194.344 -                node.className = currentClassNames.join(" ");
 194.345 -            }
 194.346 -        },
 194.347 -
 194.348 -        setTextContent: function(element, textContent) {
 194.349 -            var value = ko.utils.unwrapObservable(textContent);
 194.350 -            if ((value === null) || (value === undefined))
 194.351 -                value = "";
 194.352 -
 194.353 -            if (element.nodeType === 3) {
 194.354 -                element.data = value;
 194.355 -            } else {
 194.356 -                // We need there to be exactly one child: a text node.
 194.357 -                // If there are no children, more than one, or if it's not a text node,
 194.358 -                // we'll clear everything and create a single text node.
 194.359 -                var innerTextNode = ko.virtualElements.firstChild(element);
 194.360 -                if (!innerTextNode || innerTextNode.nodeType != 3 || ko.virtualElements.nextSibling(innerTextNode)) {
 194.361 -                    ko.virtualElements.setDomNodeChildren(element, [document.createTextNode(value)]);
 194.362 -                } else {
 194.363 -                    innerTextNode.data = value;
 194.364 -                }
 194.365 -
 194.366 -                ko.utils.forceRefresh(element);
 194.367 -            }
 194.368 -        },
 194.369 -
 194.370 -        setElementName: function(element, name) {
 194.371 -            element.name = name;
 194.372 -
 194.373 -            // Workaround IE 6/7 issue
 194.374 -            // - https://github.com/SteveSanderson/knockout/issues/197
 194.375 -            // - http://www.matts411.com/post/setting_the_name_attribute_in_ie_dom/
 194.376 -            if (ieVersion <= 7) {
 194.377 -                try {
 194.378 -                    element.mergeAttributes(document.createElement("<input name='" + element.name + "'/>"), false);
 194.379 -                }
 194.380 -                catch(e) {} // For IE9 with doc mode "IE9 Standards" and browser mode "IE9 Compatibility View"
 194.381 -            }
 194.382 -        },
 194.383 -
 194.384 -        forceRefresh: function(node) {
 194.385 -            // Workaround for an IE9 rendering bug - https://github.com/SteveSanderson/knockout/issues/209
 194.386 -            if (ieVersion >= 9) {
 194.387 -                // For text nodes and comment nodes (most likely virtual elements), we will have to refresh the container
 194.388 -                var elem = node.nodeType == 1 ? node : node.parentNode;
 194.389 -                if (elem.style)
 194.390 -                    elem.style.zoom = elem.style.zoom;
 194.391 -            }
 194.392 -        },
 194.393 -
 194.394 -        ensureSelectElementIsRenderedCorrectly: function(selectElement) {
 194.395 -            // Workaround for IE9 rendering bug - it doesn't reliably display all the text in dynamically-added select boxes unless you force it to re-render by updating the width.
 194.396 -            // (See https://github.com/SteveSanderson/knockout/issues/312, http://stackoverflow.com/questions/5908494/select-only-shows-first-char-of-selected-option)
 194.397 -            if (ieVersion >= 9) {
 194.398 -                var originalWidth = selectElement.style.width;
 194.399 -                selectElement.style.width = 0;
 194.400 -                selectElement.style.width = originalWidth;
 194.401 -            }
 194.402 -        },
 194.403 -
 194.404 -        range: function (min, max) {
 194.405 -            min = ko.utils.unwrapObservable(min);
 194.406 -            max = ko.utils.unwrapObservable(max);
 194.407 -            var result = [];
 194.408 -            for (var i = min; i <= max; i++)
 194.409 -                result.push(i);
 194.410 -            return result;
 194.411 -        },
 194.412 -
 194.413 -        makeArray: function(arrayLikeObject) {
 194.414 -            var result = [];
 194.415 -            for (var i = 0, j = arrayLikeObject.length; i < j; i++) {
 194.416 -                result.push(arrayLikeObject[i]);
 194.417 -            };
 194.418 -            return result;
 194.419 -        },
 194.420 -
 194.421 -        isIe6 : isIe6,
 194.422 -        isIe7 : isIe7,
 194.423 -        ieVersion : ieVersion,
 194.424 -
 194.425 -        getFormFields: function(form, fieldName) {
 194.426 -            var fields = ko.utils.makeArray(form.getElementsByTagName("input")).concat(ko.utils.makeArray(form.getElementsByTagName("textarea")));
 194.427 -            var isMatchingField = (typeof fieldName == 'string')
 194.428 -                ? function(field) { return field.name === fieldName }
 194.429 -                : function(field) { return fieldName.test(field.name) }; // Treat fieldName as regex or object containing predicate
 194.430 -            var matches = [];
 194.431 -            for (var i = fields.length - 1; i >= 0; i--) {
 194.432 -                if (isMatchingField(fields[i]))
 194.433 -                    matches.push(fields[i]);
 194.434 -            };
 194.435 -            return matches;
 194.436 -        },
 194.437 -
 194.438 -        parseJson: function (jsonString) {
 194.439 -            if (typeof jsonString == "string") {
 194.440 -                jsonString = ko.utils.stringTrim(jsonString);
 194.441 -                if (jsonString) {
 194.442 -                    if (window.JSON && window.JSON.parse) // Use native parsing where available
 194.443 -                        return window.JSON.parse(jsonString);
 194.444 -                    return (new Function("return " + jsonString))(); // Fallback on less safe parsing for older browsers
 194.445 -                }
 194.446 -            }
 194.447 -            return null;
 194.448 -        },
 194.449 -
 194.450 -        stringifyJson: function (data, replacer, space) {   // replacer and space are optional
 194.451 -            if ((typeof JSON == "undefined") || (typeof JSON.stringify == "undefined"))
 194.452 -                throw new Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js");
 194.453 -            return JSON.stringify(ko.utils.unwrapObservable(data), replacer, space);
 194.454 -        },
 194.455 -
 194.456 -        postJson: function (urlOrForm, data, options) {
 194.457 -            options = options || {};
 194.458 -            var params = options['params'] || {};
 194.459 -            var includeFields = options['includeFields'] || this.fieldsIncludedWithJsonPost;
 194.460 -            var url = urlOrForm;
 194.461 -
 194.462 -            // If we were given a form, use its 'action' URL and pick out any requested field values
 194.463 -            if((typeof urlOrForm == 'object') && (ko.utils.tagNameLower(urlOrForm) === "form")) {
 194.464 -                var originalForm = urlOrForm;
 194.465 -                url = originalForm.action;
 194.466 -                for (var i = includeFields.length - 1; i >= 0; i--) {
 194.467 -                    var fields = ko.utils.getFormFields(originalForm, includeFields[i]);
 194.468 -                    for (var j = fields.length - 1; j >= 0; j--)
 194.469 -                        params[fields[j].name] = fields[j].value;
 194.470 -                }
 194.471 -            }
 194.472 -
 194.473 -            data = ko.utils.unwrapObservable(data);
 194.474 -            var form = document.createElement("form");
 194.475 -            form.style.display = "none";
 194.476 -            form.action = url;
 194.477 -            form.method = "post";
 194.478 -            for (var key in data) {
 194.479 -                var input = document.createElement("input");
 194.480 -                input.name = key;
 194.481 -                input.value = ko.utils.stringifyJson(ko.utils.unwrapObservable(data[key]));
 194.482 -                form.appendChild(input);
 194.483 -            }
 194.484 -            for (var key in params) {
 194.485 -                var input = document.createElement("input");
 194.486 -                input.name = key;
 194.487 -                input.value = params[key];
 194.488 -                form.appendChild(input);
 194.489 -            }
 194.490 -            document.body.appendChild(form);
 194.491 -            options['submitter'] ? options['submitter'](form) : form.submit();
 194.492 -            setTimeout(function () { form.parentNode.removeChild(form); }, 0);
 194.493 -        }
 194.494 -    }
 194.495 -})();
 194.496 -
 194.497 -ko.exportSymbol('utils', ko.utils);
 194.498 -ko.exportSymbol('utils.arrayForEach', ko.utils.arrayForEach);
 194.499 -ko.exportSymbol('utils.arrayFirst', ko.utils.arrayFirst);
 194.500 -ko.exportSymbol('utils.arrayFilter', ko.utils.arrayFilter);
 194.501 -ko.exportSymbol('utils.arrayGetDistinctValues', ko.utils.arrayGetDistinctValues);
 194.502 -ko.exportSymbol('utils.arrayIndexOf', ko.utils.arrayIndexOf);
 194.503 -ko.exportSymbol('utils.arrayMap', ko.utils.arrayMap);
 194.504 -ko.exportSymbol('utils.arrayPushAll', ko.utils.arrayPushAll);
 194.505 -ko.exportSymbol('utils.arrayRemoveItem', ko.utils.arrayRemoveItem);
 194.506 -ko.exportSymbol('utils.extend', ko.utils.extend);
 194.507 -ko.exportSymbol('utils.fieldsIncludedWithJsonPost', ko.utils.fieldsIncludedWithJsonPost);
 194.508 -ko.exportSymbol('utils.getFormFields', ko.utils.getFormFields);
 194.509 -ko.exportSymbol('utils.peekObservable', ko.utils.peekObservable);
 194.510 -ko.exportSymbol('utils.postJson', ko.utils.postJson);
 194.511 -ko.exportSymbol('utils.parseJson', ko.utils.parseJson);
 194.512 -ko.exportSymbol('utils.registerEventHandler', ko.utils.registerEventHandler);
 194.513 -ko.exportSymbol('utils.stringifyJson', ko.utils.stringifyJson);
 194.514 -ko.exportSymbol('utils.range', ko.utils.range);
 194.515 -ko.exportSymbol('utils.toggleDomNodeCssClass', ko.utils.toggleDomNodeCssClass);
 194.516 -ko.exportSymbol('utils.triggerEvent', ko.utils.triggerEvent);
 194.517 -ko.exportSymbol('utils.unwrapObservable', ko.utils.unwrapObservable);
 194.518 -
 194.519 -if (!Function.prototype['bind']) {
 194.520 -    // Function.prototype.bind is a standard part of ECMAScript 5th Edition (December 2009, http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf)
 194.521 -    // In case the browser doesn't implement it natively, provide a JavaScript implementation. This implementation is based on the one in prototype.js
 194.522 -    Function.prototype['bind'] = function (object) {
 194.523 -        var originalFunction = this, args = Array.prototype.slice.call(arguments), object = args.shift();
 194.524 -        return function () {
 194.525 -            return originalFunction.apply(object, args.concat(Array.prototype.slice.call(arguments)));
 194.526 -        };
 194.527 -    };
 194.528 -}
 194.529 -
 194.530 -ko.utils.domData = new (function () {
 194.531 -    var uniqueId = 0;
 194.532 -    var dataStoreKeyExpandoPropertyName = "__ko__" + (new Date).getTime();
 194.533 -    var dataStore = {};
 194.534 -    return {
 194.535 -        get: function (node, key) {
 194.536 -            var allDataForNode = ko.utils.domData.getAll(node, false);
 194.537 -            return allDataForNode === undefined ? undefined : allDataForNode[key];
 194.538 -        },
 194.539 -        set: function (node, key, value) {
 194.540 -            if (value === undefined) {
 194.541 -                // Make sure we don't actually create a new domData key if we are actually deleting a value
 194.542 -                if (ko.utils.domData.getAll(node, false) === undefined)
 194.543 -                    return;
 194.544 -            }
 194.545 -            var allDataForNode = ko.utils.domData.getAll(node, true);
 194.546 -            allDataForNode[key] = value;
 194.547 -        },
 194.548 -        getAll: function (node, createIfNotFound) {
 194.549 -            var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
 194.550 -            var hasExistingDataStore = dataStoreKey && (dataStoreKey !== "null") && dataStore[dataStoreKey];
 194.551 -            if (!hasExistingDataStore) {
 194.552 -                if (!createIfNotFound)
 194.553 -                    return undefined;
 194.554 -                dataStoreKey = node[dataStoreKeyExpandoPropertyName] = "ko" + uniqueId++;
 194.555 -                dataStore[dataStoreKey] = {};
 194.556 -            }
 194.557 -            return dataStore[dataStoreKey];
 194.558 -        },
 194.559 -        clear: function (node) {
 194.560 -            var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
 194.561 -            if (dataStoreKey) {
 194.562 -                delete dataStore[dataStoreKey];
 194.563 -                node[dataStoreKeyExpandoPropertyName] = null;
 194.564 -                return true; // Exposing "did clean" flag purely so specs can infer whether things have been cleaned up as intended
 194.565 -            }
 194.566 -            return false;
 194.567 -        }
 194.568 -    }
 194.569 -})();
 194.570 -
 194.571 -ko.exportSymbol('utils.domData', ko.utils.domData);
 194.572 -ko.exportSymbol('utils.domData.clear', ko.utils.domData.clear); // Exporting only so specs can clear up after themselves fully
 194.573 -
 194.574 -ko.utils.domNodeDisposal = new (function () {
 194.575 -    var domDataKey = "__ko_domNodeDisposal__" + (new Date).getTime();
 194.576 -    var cleanableNodeTypes = { 1: true, 8: true, 9: true };       // Element, Comment, Document
 194.577 -    var cleanableNodeTypesWithDescendants = { 1: true, 9: true }; // Element, Document
 194.578 -
 194.579 -    function getDisposeCallbacksCollection(node, createIfNotFound) {
 194.580 -        var allDisposeCallbacks = ko.utils.domData.get(node, domDataKey);
 194.581 -        if ((allDisposeCallbacks === undefined) && createIfNotFound) {
 194.582 -            allDisposeCallbacks = [];
 194.583 -            ko.utils.domData.set(node, domDataKey, allDisposeCallbacks);
 194.584 -        }
 194.585 -        return allDisposeCallbacks;
 194.586 -    }
 194.587 -    function destroyCallbacksCollection(node) {
 194.588 -        ko.utils.domData.set(node, domDataKey, undefined);
 194.589 -    }
 194.590 -
 194.591 -    function cleanSingleNode(node) {
 194.592 -        // Run all the dispose callbacks
 194.593 -        var callbacks = getDisposeCallbacksCollection(node, false);
 194.594 -        if (callbacks) {
 194.595 -            callbacks = callbacks.slice(0); // Clone, as the array may be modified during iteration (typically, callbacks will remove themselves)
 194.596 -            for (var i = 0; i < callbacks.length; i++)
 194.597 -                callbacks[i](node);
 194.598 -        }
 194.599 -
 194.600 -        // Also erase the DOM data
 194.601 -        ko.utils.domData.clear(node);
 194.602 -
 194.603 -        // Special support for jQuery here because it's so commonly used.
 194.604 -        // Many jQuery plugins (including jquery.tmpl) store data using jQuery's equivalent of domData
 194.605 -        // so notify it to tear down any resources associated with the node & descendants here.
 194.606 -        if ((typeof jQuery == "function") && (typeof jQuery['cleanData'] == "function"))
 194.607 -            jQuery['cleanData']([node]);
 194.608 -
 194.609 -        // Also clear any immediate-child comment nodes, as these wouldn't have been found by
 194.610 -        // node.getElementsByTagName("*") in cleanNode() (comment nodes aren't elements)
 194.611 -        if (cleanableNodeTypesWithDescendants[node.nodeType])
 194.612 -            cleanImmediateCommentTypeChildren(node);
 194.613 -    }
 194.614 -
 194.615 -    function cleanImmediateCommentTypeChildren(nodeWithChildren) {
 194.616 -        var child, nextChild = nodeWithChildren.firstChild;
 194.617 -        while (child = nextChild) {
 194.618 -            nextChild = child.nextSibling;
 194.619 -            if (child.nodeType === 8)
 194.620 -                cleanSingleNode(child);
 194.621 -        }
 194.622 -    }
 194.623 -
 194.624 -    return {
 194.625 -        addDisposeCallback : function(node, callback) {
 194.626 -            if (typeof callback != "function")
 194.627 -                throw new Error("Callback must be a function");
 194.628 -            getDisposeCallbacksCollection(node, true).push(callback);
 194.629 -        },
 194.630 -
 194.631 -        removeDisposeCallback : function(node, callback) {
 194.632 -            var callbacksCollection = getDisposeCallbacksCollection(node, false);
 194.633 -            if (callbacksCollection) {
 194.634 -                ko.utils.arrayRemoveItem(callbacksCollection, callback);
 194.635 -                if (callbacksCollection.length == 0)
 194.636 -                    destroyCallbacksCollection(node);
 194.637 -            }
 194.638 -        },
 194.639 -
 194.640 -        cleanNode : function(node) {
 194.641 -            // First clean this node, where applicable
 194.642 -            if (cleanableNodeTypes[node.nodeType]) {
 194.643 -                cleanSingleNode(node);
 194.644 -
 194.645 -                // ... then its descendants, where applicable
 194.646 -                if (cleanableNodeTypesWithDescendants[node.nodeType]) {
 194.647 -                    // Clone the descendants list in case it changes during iteration
 194.648 -                    var descendants = [];
 194.649 -                    ko.utils.arrayPushAll(descendants, node.getElementsByTagName("*"));
 194.650 -                    for (var i = 0, j = descendants.length; i < j; i++)
 194.651 -                        cleanSingleNode(descendants[i]);
 194.652 -                }
 194.653 -            }
 194.654 -            return node;
 194.655 -        },
 194.656 -
 194.657 -        removeNode : function(node) {
 194.658 -            ko.cleanNode(node);
 194.659 -            if (node.parentNode)
 194.660 -                node.parentNode.removeChild(node);
 194.661 -        }
 194.662 -    }
 194.663 -})();
 194.664 -ko.cleanNode = ko.utils.domNodeDisposal.cleanNode; // Shorthand name for convenience
 194.665 -ko.removeNode = ko.utils.domNodeDisposal.removeNode; // Shorthand name for convenience
 194.666 -ko.exportSymbol('cleanNode', ko.cleanNode);
 194.667 -ko.exportSymbol('removeNode', ko.removeNode);
 194.668 -ko.exportSymbol('utils.domNodeDisposal', ko.utils.domNodeDisposal);
 194.669 -ko.exportSymbol('utils.domNodeDisposal.addDisposeCallback', ko.utils.domNodeDisposal.addDisposeCallback);
 194.670 -ko.exportSymbol('utils.domNodeDisposal.removeDisposeCallback', ko.utils.domNodeDisposal.removeDisposeCallback);
 194.671 -(function () {
 194.672 -    var leadingCommentRegex = /^(\s*)<!--(.*?)-->/;
 194.673 -
 194.674 -    function simpleHtmlParse(html) {
 194.675 -        // Based on jQuery's "clean" function, but only accounting for table-related elements.
 194.676 -        // If you have referenced jQuery, this won't be used anyway - KO will use jQuery's "clean" function directly
 194.677 -
 194.678 -        // Note that there's still an issue in IE < 9 whereby it will discard comment nodes that are the first child of
 194.679 -        // a descendant node. For example: "<div><!-- mycomment -->abc</div>" will get parsed as "<div>abc</div>"
 194.680 -        // This won't affect anyone who has referenced jQuery, and there's always the workaround of inserting a dummy node
 194.681 -        // (possibly a text node) in front of the comment. So, KO does not attempt to workaround this IE issue automatically at present.
 194.682 -
 194.683 -        // Trim whitespace, otherwise indexOf won't work as expected
 194.684 -        var tags = ko.utils.stringTrim(html).toLowerCase(), div = document.createElement("div");
 194.685 -
 194.686 -        // Finds the first match from the left column, and returns the corresponding "wrap" data from the right column
 194.687 -        var wrap = tags.match(/^<(thead|tbody|tfoot)/)              && [1, "<table>", "</table>"] ||
 194.688 -                   !tags.indexOf("<tr")                             && [2, "<table><tbody>", "</tbody></table>"] ||
 194.689 -                   (!tags.indexOf("<td") || !tags.indexOf("<th"))   && [3, "<table><tbody><tr>", "</tr></tbody></table>"] ||
 194.690 -                   /* anything else */                                 [0, "", ""];
 194.691 -
 194.692 -        // Go to html and back, then peel off extra wrappers
 194.693 -        // Note that we always prefix with some dummy text, because otherwise, IE<9 will strip out leading comment nodes in descendants. Total madness.
 194.694 -        var markup = "ignored<div>" + wrap[1] + html + wrap[2] + "</div>";
 194.695 -        if (typeof window['innerShiv'] == "function") {
 194.696 -            div.appendChild(window['innerShiv'](markup));
 194.697 -        } else {
 194.698 -            div.innerHTML = markup;
 194.699 -        }
 194.700 -
 194.701 -        // Move to the right depth
 194.702 -        while (wrap[0]--)
 194.703 -            div = div.lastChild;
 194.704 -
 194.705 -        return ko.utils.makeArray(div.lastChild.childNodes);
 194.706 -    }
 194.707 -
 194.708 -    function jQueryHtmlParse(html) {
 194.709 -        // jQuery's "parseHTML" function was introduced in jQuery 1.8.0 and is a documented public API.
 194.710 -        if (jQuery['parseHTML']) {
 194.711 -            return jQuery['parseHTML'](html);
 194.712 -        } else {
 194.713 -            // For jQuery < 1.8.0, we fall back on the undocumented internal "clean" function.
 194.714 -            var elems = jQuery['clean']([html]);
 194.715 -
 194.716 -            // As of jQuery 1.7.1, jQuery parses the HTML by appending it to some dummy parent nodes held in an in-memory document fragment.
 194.717 -            // Unfortunately, it never clears the dummy parent nodes from the document fragment, so it leaks memory over time.
 194.718 -            // Fix this by finding the top-most dummy parent element, and detaching it from its owner fragment.
 194.719 -            if (elems && elems[0]) {
 194.720 -                // Find the top-most parent element that's a direct child of a document fragment
 194.721 -                var elem = elems[0];
 194.722 -                while (elem.parentNode && elem.parentNode.nodeType !== 11 /* i.e., DocumentFragment */)
 194.723 -                    elem = elem.parentNode;
 194.724 -                // ... then detach it
 194.725 -                if (elem.parentNode)
 194.726 -                    elem.parentNode.removeChild(elem);
 194.727 -            }
 194.728 -
 194.729 -            return elems;
 194.730 -        }
 194.731 -    }
 194.732 -
 194.733 -    ko.utils.parseHtmlFragment = function(html) {
 194.734 -        return typeof jQuery != 'undefined' ? jQueryHtmlParse(html)   // As below, benefit from jQuery's optimisations where possible
 194.735 -                                            : simpleHtmlParse(html);  // ... otherwise, this simple logic will do in most common cases.
 194.736 -    };
 194.737 -
 194.738 -    ko.utils.setHtml = function(node, html) {
 194.739 -        ko.utils.emptyDomNode(node);
 194.740 -
 194.741 -        // There's no legitimate reason to display a stringified observable without unwrapping it, so we'll unwrap it
 194.742 -        html = ko.utils.unwrapObservable(html);
 194.743 -
 194.744 -        if ((html !== null) && (html !== undefined)) {
 194.745 -            if (typeof html != 'string')
 194.746 -                html = html.toString();
 194.747 -
 194.748 -            // jQuery contains a lot of sophisticated code to parse arbitrary HTML fragments,
 194.749 -            // for example <tr> elements which are not normally allowed to exist on their own.
 194.750 -            // If you've referenced jQuery we'll use that rather than duplicating its code.
 194.751 -            if (typeof jQuery != 'undefined') {
 194.752 -                jQuery(node)['html'](html);
 194.753 -            } else {
 194.754 -                // ... otherwise, use KO's own parsing logic.
 194.755 -                var parsedNodes = ko.utils.parseHtmlFragment(html);
 194.756 -                for (var i = 0; i < parsedNodes.length; i++)
 194.757 -                    node.appendChild(parsedNodes[i]);
 194.758 -            }
 194.759 -        }
 194.760 -    };
 194.761 -})();
 194.762 -
 194.763 -ko.exportSymbol('utils.parseHtmlFragment', ko.utils.parseHtmlFragment);
 194.764 -ko.exportSymbol('utils.setHtml', ko.utils.setHtml);
 194.765 -
 194.766 -ko.memoization = (function () {
 194.767 -    var memos = {};
 194.768 -
 194.769 -    function randomMax8HexChars() {
 194.770 -        return (((1 + Math.random()) * 0x100000000) | 0).toString(16).substring(1);
 194.771 -    }
 194.772 -    function generateRandomId() {
 194.773 -        return randomMax8HexChars() + randomMax8HexChars();
 194.774 -    }
 194.775 -    function findMemoNodes(rootNode, appendToArray) {
 194.776 -        if (!rootNode)
 194.777 -            return;
 194.778 -        if (rootNode.nodeType == 8) {
 194.779 -            var memoId = ko.memoization.parseMemoText(rootNode.nodeValue);
 194.780 -            if (memoId != null)
 194.781 -                appendToArray.push({ domNode: rootNode, memoId: memoId });
 194.782 -        } else if (rootNode.nodeType == 1) {
 194.783 -            for (var i = 0, childNodes = rootNode.childNodes, j = childNodes.length; i < j; i++)
 194.784 -                findMemoNodes(childNodes[i], appendToArray);
 194.785 -        }
 194.786 -    }
 194.787 -
 194.788 -    return {
 194.789 -        memoize: function (callback) {
 194.790 -            if (typeof callback != "function")
 194.791 -                throw new Error("You can only pass a function to ko.memoization.memoize()");
 194.792 -            var memoId = generateRandomId();
 194.793 -            memos[memoId] = callback;
 194.794 -            return "<!--[ko_memo:" + memoId + "]-->";
 194.795 -        },
 194.796 -
 194.797 -        unmemoize: function (memoId, callbackParams) {
 194.798 -            var callback = memos[memoId];
 194.799 -            if (callback === undefined)
 194.800 -                throw new Error("Couldn't find any memo with ID " + memoId + ". Perhaps it's already been unmemoized.");
 194.801 -            try {
 194.802 -                callback.apply(null, callbackParams || []);
 194.803 -                return true;
 194.804 -            }
 194.805 -            finally { delete memos[memoId]; }
 194.806 -        },
 194.807 -
 194.808 -        unmemoizeDomNodeAndDescendants: function (domNode, extraCallbackParamsArray) {
 194.809 -            var memos = [];
 194.810 -            findMemoNodes(domNode, memos);
 194.811 -            for (var i = 0, j = memos.length; i < j; i++) {
 194.812 -                var node = memos[i].domNode;
 194.813 -                var combinedParams = [node];
 194.814 -                if (extraCallbackParamsArray)
 194.815 -                    ko.utils.arrayPushAll(combinedParams, extraCallbackParamsArray);
 194.816 -                ko.memoization.unmemoize(memos[i].memoId, combinedParams);
 194.817 -                node.nodeValue = ""; // Neuter this node so we don't try to unmemoize it again
 194.818 -                if (node.parentNode)
 194.819 -                    node.parentNode.removeChild(node); // If possible, erase it totally (not always possible - someone else might just hold a reference to it then call unmemoizeDomNodeAndDescendants again)
 194.820 -            }
 194.821 -        },
 194.822 -
 194.823 -        parseMemoText: function (memoText) {
 194.824 -            var match = memoText.match(/^\[ko_memo\:(.*?)\]$/);
 194.825 -            return match ? match[1] : null;
 194.826 -        }
 194.827 -    };
 194.828 -})();
 194.829 -
 194.830 -ko.exportSymbol('memoization', ko.memoization);
 194.831 -ko.exportSymbol('memoization.memoize', ko.memoization.memoize);
 194.832 -ko.exportSymbol('memoization.unmemoize', ko.memoization.unmemoize);
 194.833 -ko.exportSymbol('memoization.parseMemoText', ko.memoization.parseMemoText);
 194.834 -ko.exportSymbol('memoization.unmemoizeDomNodeAndDescendants', ko.memoization.unmemoizeDomNodeAndDescendants);
 194.835 -ko.extenders = {
 194.836 -    'throttle': function(target, timeout) {
 194.837 -        // Throttling means two things:
 194.838 -
 194.839 -        // (1) For dependent observables, we throttle *evaluations* so that, no matter how fast its dependencies
 194.840 -        //     notify updates, the target doesn't re-evaluate (and hence doesn't notify) faster than a certain rate
 194.841 -        target['throttleEvaluation'] = timeout;
 194.842 -
 194.843 -        // (2) For writable targets (observables, or writable dependent observables), we throttle *writes*
 194.844 -        //     so the target cannot change value synchronously or faster than a certain rate
 194.845 -        var writeTimeoutInstance = null;
 194.846 -        return ko.dependentObservable({
 194.847 -            'read': target,
 194.848 -            'write': function(value) {
 194.849 -                clearTimeout(writeTimeoutInstance);
 194.850 -                writeTimeoutInstance = setTimeout(function() {
 194.851 -                    target(value);
 194.852 -                }, timeout);
 194.853 -            }
 194.854 -        });
 194.855 -    },
 194.856 -
 194.857 -    'notify': function(target, notifyWhen) {
 194.858 -        target["equalityComparer"] = notifyWhen == "always"
 194.859 -            ? function() { return false } // Treat all values as not equal
 194.860 -            : ko.observable["fn"]["equalityComparer"];
 194.861 -        return target;
 194.862 -    }
 194.863 -};
 194.864 -
 194.865 -function applyExtenders(requestedExtenders) {
 194.866 -    var target = this;
 194.867 -    if (requestedExtenders) {
 194.868 -        for (var key in requestedExtenders) {
 194.869 -            var extenderHandler = ko.extenders[key];
 194.870 -            if (typeof extenderHandler == 'function') {
 194.871 -                target = extenderHandler(target, requestedExtenders[key]);
 194.872 -            }
 194.873 -        }
 194.874 -    }
 194.875 -    return target;
 194.876 -}
 194.877 -
 194.878 -ko.exportSymbol('extenders', ko.extenders);
 194.879 -
 194.880 -ko.subscription = function (target, callback, disposeCallback) {
 194.881 -    this.target = target;
 194.882 -    this.callback = callback;
 194.883 -    this.disposeCallback = disposeCallback;
 194.884 -    ko.exportProperty(this, 'dispose', this.dispose);
 194.885 -};
 194.886 -ko.subscription.prototype.dispose = function () {
 194.887 -    this.isDisposed = true;
 194.888 -    this.disposeCallback();
 194.889 -};
 194.890 -
 194.891 -ko.subscribable = function () {
 194.892 -    this._subscriptions = {};
 194.893 -
 194.894 -    ko.utils.extend(this, ko.subscribable['fn']);
 194.895 -    ko.exportProperty(this, 'subscribe', this.subscribe);
 194.896 -    ko.exportProperty(this, 'extend', this.extend);
 194.897 -    ko.exportProperty(this, 'getSubscriptionsCount', this.getSubscriptionsCount);
 194.898 -}
 194.899 -
 194.900 -var defaultEvent = "change";
 194.901 -
 194.902 -ko.subscribable['fn'] = {
 194.903 -    subscribe: function (callback, callbackTarget, event) {
 194.904 -        event = event || defaultEvent;
 194.905 -        var boundCallback = callbackTarget ? callback.bind(callbackTarget) : callback;
 194.906 -
 194.907 -        var subscription = new ko.subscription(this, boundCallback, function () {
 194.908 -            ko.utils.arrayRemoveItem(this._subscriptions[event], subscription);
 194.909 -        }.bind(this));
 194.910 -
 194.911 -        if (!this._subscriptions[event])
 194.912 -            this._subscriptions[event] = [];
 194.913 -        this._subscriptions[event].push(subscription);
 194.914 -        return subscription;
 194.915 -    },
 194.916 -
 194.917 -    "notifySubscribers": function (valueToNotify, event) {
 194.918 -        event = event || defaultEvent;
 194.919 -        if (this._subscriptions[event]) {
 194.920 -            ko.dependencyDetection.ignore(function() {
 194.921 -                ko.utils.arrayForEach(this._subscriptions[event].slice(0), function (subscription) {
 194.922 -                    // In case a subscription was disposed during the arrayForEach cycle, check
 194.923 -                    // for isDisposed on each subscription before invoking its callback
 194.924 -                    if (subscription && (subscription.isDisposed !== true))
 194.925 -                        subscription.callback(valueToNotify);
 194.926 -                });
 194.927 -            }, this);
 194.928 -        }
 194.929 -    },
 194.930 -
 194.931 -    getSubscriptionsCount: function () {
 194.932 -        var total = 0;
 194.933 -        for (var eventName in this._subscriptions) {
 194.934 -            if (this._subscriptions.hasOwnProperty(eventName))
 194.935 -                total += this._subscriptions[eventName].length;
 194.936 -        }
 194.937 -        return total;
 194.938 -    },
 194.939 -
 194.940 -    extend: applyExtenders
 194.941 -};
 194.942 -
 194.943 -
 194.944 -ko.isSubscribable = function (instance) {
 194.945 -    return typeof instance.subscribe == "function" && typeof instance["notifySubscribers"] == "function";
 194.946 -};
 194.947 -
 194.948 -ko.exportSymbol('subscribable', ko.subscribable);
 194.949 -ko.exportSymbol('isSubscribable', ko.isSubscribable);
 194.950 -
 194.951 -ko.dependencyDetection = (function () {
 194.952 -    var _frames = [];
 194.953 -
 194.954 -    return {
 194.955 -        begin: function (callback) {
 194.956 -            _frames.push({ callback: callback, distinctDependencies:[] });
 194.957 -        },
 194.958 -
 194.959 -        end: function () {
 194.960 -            _frames.pop();
 194.961 -        },
 194.962 -
 194.963 -        registerDependency: function (subscribable) {
 194.964 -            if (!ko.isSubscribable(subscribable))
 194.965 -                throw new Error("Only subscribable things can act as dependencies");
 194.966 -            if (_frames.length > 0) {
 194.967 -                var topFrame = _frames[_frames.length - 1];
 194.968 -                if (!topFrame || ko.utils.arrayIndexOf(topFrame.distinctDependencies, subscribable) >= 0)
 194.969 -                    return;
 194.970 -                topFrame.distinctDependencies.push(subscribable);
 194.971 -                topFrame.callback(subscribable);
 194.972 -            }
 194.973 -        },
 194.974 -
 194.975 -        ignore: function(callback, callbackTarget, callbackArgs) {
 194.976 -            try {
 194.977 -                _frames.push(null);
 194.978 -                return callback.apply(callbackTarget, callbackArgs || []);
 194.979 -            } finally {
 194.980 -                _frames.pop();
 194.981 -            }
 194.982 -        }
 194.983 -    };
 194.984 -})();
 194.985 -var primitiveTypes = { 'undefined':true, 'boolean':true, 'number':true, 'string':true };
 194.986 -
 194.987 -ko.observable = function (initialValue) {
 194.988 -    var _latestValue = initialValue;
 194.989 -
 194.990 -    function observable() {
 194.991 -        if (arguments.length > 0) {
 194.992 -            // Write
 194.993 -
 194.994 -            // Ignore writes if the value hasn't changed
 194.995 -            if ((!observable['equalityComparer']) || !observable['equalityComparer'](_latestValue, arguments[0])) {
 194.996 -                observable.valueWillMutate();
 194.997 -                _latestValue = arguments[0];
 194.998 -                if (DEBUG) observable._latestValue = _latestValue;
 194.999 -                observable.valueHasMutated();
194.1000 -            }
194.1001 -            return this; // Permits chained assignments
194.1002 -        }
194.1003 -        else {
194.1004 -            // Read
194.1005 -            ko.dependencyDetection.registerDependency(observable); // The caller only needs to be notified of changes if they did a "read" operation
194.1006 -            return _latestValue;
194.1007 -        }
194.1008 -    }
194.1009 -    if (DEBUG) observable._latestValue = _latestValue;
194.1010 -    ko.subscribable.call(observable);
194.1011 -    observable.peek = function() { return _latestValue };
194.1012 -    observable.valueHasMutated = function () { observable["notifySubscribers"](_latestValue); }
194.1013 -    observable.valueWillMutate = function () { observable["notifySubscribers"](_latestValue, "beforeChange"); }
194.1014 -    ko.utils.extend(observable, ko.observable['fn']);
194.1015 -
194.1016 -    ko.exportProperty(observable, 'peek', observable.peek);
194.1017 -    ko.exportProperty(observable, "valueHasMutated", observable.valueHasMutated);
194.1018 -    ko.exportProperty(observable, "valueWillMutate", observable.valueWillMutate);
194.1019 -
194.1020 -    return observable;
194.1021 -}
194.1022 -
194.1023 -ko.observable['fn'] = {
194.1024 -    "equalityComparer": function valuesArePrimitiveAndEqual(a, b) {
194.1025 -        var oldValueIsPrimitive = (a === null) || (typeof(a) in primitiveTypes);
194.1026 -        return oldValueIsPrimitive ? (a === b) : false;
194.1027 -    }
194.1028 -};
194.1029 -
194.1030 -var protoProperty = ko.observable.protoProperty = "__ko_proto__";
194.1031 -ko.observable['fn'][protoProperty] = ko.observable;
194.1032 -
194.1033 -ko.hasPrototype = function(instance, prototype) {
194.1034 -    if ((instance === null) || (instance === undefined) || (instance[protoProperty] === undefined)) return false;
194.1035 -    if (instance[protoProperty] === prototype) return true;
194.1036 -    return ko.hasPrototype(instance[protoProperty], prototype); // Walk the prototype chain
194.1037 -};
194.1038 -
194.1039 -ko.isObservable = function (instance) {
194.1040 -    return ko.hasPrototype(instance, ko.observable);
194.1041 -}
194.1042 -ko.isWriteableObservable = function (instance) {
194.1043 -    // Observable
194.1044 -    if ((typeof instance == "function") && instance[protoProperty] === ko.observable)
194.1045 -        return true;
194.1046 -    // Writeable dependent observable
194.1047 -    if ((typeof instance == "function") && (instance[protoProperty] === ko.dependentObservable) && (instance.hasWriteFunction))
194.1048 -        return true;
194.1049 -    // Anything else
194.1050 -    return false;
194.1051 -}
194.1052 -
194.1053 -
194.1054 -ko.exportSymbol('observable', ko.observable);
194.1055 -ko.exportSymbol('isObservable', ko.isObservable);
194.1056 -ko.exportSymbol('isWriteableObservable', ko.isWriteableObservable);
194.1057 -ko.observableArray = function (initialValues) {
194.1058 -    if (arguments.length == 0) {
194.1059 -        // Zero-parameter constructor initializes to empty array
194.1060 -        initialValues = [];
194.1061 -    }
194.1062 -    if ((initialValues !== null) && (initialValues !== undefined) && !('length' in initialValues))
194.1063 -        throw new Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");
194.1064 -
194.1065 -    var result = ko.observable(initialValues);
194.1066 -    ko.utils.extend(result, ko.observableArray['fn']);
194.1067 -    return result;
194.1068 -}
194.1069 -
194.1070 -ko.observableArray['fn'] = {
194.1071 -    'remove': function (valueOrPredicate) {
194.1072 -        var underlyingArray = this.peek();
194.1073 -        var removedValues = [];
194.1074 -        var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
194.1075 -        for (var i = 0; i < underlyingArray.length; i++) {
194.1076 -            var value = underlyingArray[i];
194.1077 -            if (predicate(value)) {
194.1078 -                if (removedValues.length === 0) {
194.1079 -                    this.valueWillMutate();
194.1080 -                }
194.1081 -                removedValues.push(value);
194.1082 -                underlyingArray.splice(i, 1);
194.1083 -                i--;
194.1084 -            }
194.1085 -        }
194.1086 -        if (removedValues.length) {
194.1087 -            this.valueHasMutated();
194.1088 -        }
194.1089 -        return removedValues;
194.1090 -    },
194.1091 -
194.1092 -    'removeAll': function (arrayOfValues) {
194.1093 -        // If you passed zero args, we remove everything
194.1094 -        if (arrayOfValues === undefined) {
194.1095 -            var underlyingArray = this.peek();
194.1096 -            var allValues = underlyingArray.slice(0);
194.1097 -            this.valueWillMutate();
194.1098 -            underlyingArray.splice(0, underlyingArray.length);
194.1099 -            this.valueHasMutated();
194.1100 -            return allValues;
194.1101 -        }
194.1102 -        // If you passed an arg, we interpret it as an array of entries to remove
194.1103 -        if (!arrayOfValues)
194.1104 -            return [];
194.1105 -        return this['remove'](function (value) {
194.1106 -            return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
194.1107 -        });
194.1108 -    },
194.1109 -
194.1110 -    'destroy': function (valueOrPredicate) {
194.1111 -        var underlyingArray = this.peek();
194.1112 -        var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
194.1113 -        this.valueWillMutate();
194.1114 -        for (var i = underlyingArray.length - 1; i >= 0; i--) {
194.1115 -            var value = underlyingArray[i];
194.1116 -            if (predicate(value))
194.1117 -                underlyingArray[i]["_destroy"] = true;
194.1118 -        }
194.1119 -        this.valueHasMutated();
194.1120 -    },
194.1121 -
194.1122 -    'destroyAll': function (arrayOfValues) {
194.1123 -        // If you passed zero args, we destroy everything
194.1124 -        if (arrayOfValues === undefined)
194.1125 -            return this['destroy'](function() { return true });
194.1126 -
194.1127 -        // If you passed an arg, we interpret it as an array of entries to destroy
194.1128 -        if (!arrayOfValues)
194.1129 -            return [];
194.1130 -        return this['destroy'](function (value) {
194.1131 -            return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
194.1132 -        });
194.1133 -    },
194.1134 -
194.1135 -    'indexOf': function (item) {
194.1136 -        var underlyingArray = this();
194.1137 -        return ko.utils.arrayIndexOf(underlyingArray, item);
194.1138 -    },
194.1139 -
194.1140 -    'replace': function(oldItem, newItem) {
194.1141 -        var index = this['indexOf'](oldItem);
194.1142 -        if (index >= 0) {
194.1143 -            this.valueWillMutate();
194.1144 -            this.peek()[index] = newItem;
194.1145 -            this.valueHasMutated();
194.1146 -        }
194.1147 -    }
194.1148 -}
194.1149 -
194.1150 -// Populate ko.observableArray.fn with read/write functions from native arrays
194.1151 -// Important: Do not add any additional functions here that may reasonably be used to *read* data from the array
194.1152 -// because we'll eval them without causing subscriptions, so ko.computed output could end up getting stale
194.1153 -ko.utils.arrayForEach(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function (methodName) {
194.1154 -    ko.observableArray['fn'][methodName] = function () {
194.1155 -        // Use "peek" to avoid creating a subscription in any computed that we're executing in the context of
194.1156 -        // (for consistency with mutating regular observables)
194.1157 -        var underlyingArray = this.peek();
194.1158 -        this.valueWillMutate();
194.1159 -        var methodCallResult = underlyingArray[methodName].apply(underlyingArray, arguments);
194.1160 -        this.valueHasMutated();
194.1161 -        return methodCallResult;
194.1162 -    };
194.1163 -});
194.1164 -
194.1165 -// Populate ko.observableArray.fn with read-only functions from native arrays
194.1166 -ko.utils.arrayForEach(["slice"], function (methodName) {
194.1167 -    ko.observableArray['fn'][methodName] = function () {
194.1168 -        var underlyingArray = this();
194.1169 -        return underlyingArray[methodName].apply(underlyingArray, arguments);
194.1170 -    };
194.1171 -});
194.1172 -
194.1173 -ko.exportSymbol('observableArray', ko.observableArray);
194.1174 -ko.dependentObservable = function (evaluatorFunctionOrOptions, evaluatorFunctionTarget, options) {
194.1175 -    var _latestValue,
194.1176 -        _hasBeenEvaluated = false,
194.1177 -        _isBeingEvaluated = false,
194.1178 -        readFunction = evaluatorFunctionOrOptions;
194.1179 -
194.1180 -    if (readFunction && typeof readFunction == "object") {
194.1181 -        // Single-parameter syntax - everything is on this "options" param
194.1182 -        options = readFunction;
194.1183 -        readFunction = options["read"];
194.1184 -    } else {
194.1185 -        // Multi-parameter syntax - construct the options according to the params passed
194.1186 -        options = options || {};
194.1187 -        if (!readFunction)
194.1188 -            readFunction = options["read"];
194.1189 -    }
194.1190 -    if (typeof readFunction != "function")
194.1191 -        throw new Error("Pass a function that returns the value of the ko.computed");
194.1192 -
194.1193 -    function addSubscriptionToDependency(subscribable) {
194.1194 -        _subscriptionsToDependencies.push(subscribable.subscribe(evaluatePossiblyAsync));
194.1195 -    }
194.1196 -
194.1197 -    function disposeAllSubscriptionsToDependencies() {
194.1198 -        ko.utils.arrayForEach(_subscriptionsToDependencies, function (subscription) {
194.1199 -            subscription.dispose();
194.1200 -        });
194.1201 -        _subscriptionsToDependencies = [];
194.1202 -    }
194.1203 -
194.1204 -    function evaluatePossiblyAsync() {
194.1205 -        var throttleEvaluationTimeout = dependentObservable['throttleEvaluation'];
194.1206 -        if (throttleEvaluationTimeout && throttleEvaluationTimeout >= 0) {
194.1207 -            clearTimeout(evaluationTimeoutInstance);
194.1208 -            evaluationTimeoutInstance = setTimeout(evaluateImmediate, throttleEvaluationTimeout);
194.1209 -        } else
194.1210 -            evaluateImmediate();
194.1211 -    }
194.1212 -
194.1213 -    function evaluateImmediate() {
194.1214 -        if (_isBeingEvaluated) {
194.1215 -            // If the evaluation of a ko.computed causes side effects, it's possible that it will trigger its own re-evaluation.
194.1216 -            // This is not desirable (it's hard for a developer to realise a chain of dependencies might cause this, and they almost
194.1217 -            // certainly didn't intend infinite re-evaluations). So, for predictability, we simply prevent ko.computeds from causing
194.1218 -            // their own re-evaluation. Further discussion at https://github.com/SteveSanderson/knockout/pull/387
194.1219 -            return;
194.1220 -        }
194.1221 -
194.1222 -        // Don't dispose on first evaluation, because the "disposeWhen" callback might
194.1223 -        // e.g., dispose when the associated DOM element isn't in the doc, and it's not
194.1224 -        // going to be in the doc until *after* the first evaluation
194.1225 -        if (_hasBeenEvaluated && disposeWhen()) {
194.1226 -            dispose();
194.1227 -            return;
194.1228 -        }
194.1229 -
194.1230 -        _isBeingEvaluated = true;
194.1231 -        try {
194.1232 -            // Initially, we assume that none of the subscriptions are still being used (i.e., all are candidates for disposal).
194.1233 -            // Then, during evaluation, we cross off any that are in fact still being used.
194.1234 -            var disposalCandidates = ko.utils.arrayMap(_subscriptionsToDependencies, function(item) {return item.target;});
194.1235 -
194.1236 -            ko.dependencyDetection.begin(function(subscribable) {
194.1237 -                var inOld;
194.1238 -                if ((inOld = ko.utils.arrayIndexOf(disposalCandidates, subscribable)) >= 0)
194.1239 -                    disposalCandidates[inOld] = undefined; // Don't want to dispose this subscription, as it's still being used
194.1240 -                else
194.1241 -                    addSubscriptionToDependency(subscribable); // Brand new subscription - add it
194.1242 -            });
194.1243 -
194.1244 -            var newValue = readFunction.call(evaluatorFunctionTarget);
194.1245 -
194.1246 -            // For each subscription no longer being used, remove it from the active subscriptions list and dispose it
194.1247 -            for (var i = disposalCandidates.length - 1; i >= 0; i--) {
194.1248 -                if (disposalCandidates[i])
194.1249 -                    _subscriptionsToDependencies.splice(i, 1)[0].dispose();
194.1250 -            }
194.1251 -            _hasBeenEvaluated = true;
194.1252 -
194.1253 -            dependentObservable["notifySubscribers"](_latestValue, "beforeChange");
194.1254 -            _latestValue = newValue;
194.1255 -            if (DEBUG) dependentObservable._latestValue = _latestValue;
194.1256 -        } finally {
194.1257 -            ko.dependencyDetection.end();
194.1258 -        }
194.1259 -
194.1260 -        dependentObservable["notifySubscribers"](_latestValue);
194.1261 -        _isBeingEvaluated = false;
194.1262 -        if (!_subscriptionsToDependencies.length)
194.1263 -            dispose();
194.1264 -    }
194.1265 -
194.1266 -    function dependentObservable() {
194.1267 -        if (arguments.length > 0) {
194.1268 -            if (typeof writeFunction === "function") {
194.1269 -                // Writing a value
194.1270 -                writeFunction.apply(evaluatorFunctionTarget, arguments);
194.1271 -            } else {
194.1272 -                throw new Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.");
194.1273 -            }
194.1274 -            return this; // Permits chained assignments
194.1275 -        } else {
194.1276 -            // Reading the value
194.1277 -            if (!_hasBeenEvaluated)
194.1278 -                evaluateImmediate();
194.1279 -            ko.dependencyDetection.registerDependency(dependentObservable);
194.1280 -            return _latestValue;
194.1281 -        }
194.1282 -    }
194.1283 -
194.1284 -    function peek() {
194.1285 -        if (!_hasBeenEvaluated)
194.1286 -            evaluateImmediate();
194.1287 -        return _latestValue;
194.1288 -    }
194.1289 -
194.1290 -    function isActive() {
194.1291 -        return !_hasBeenEvaluated || _subscriptionsToDependencies.length > 0;
194.1292 -    }
194.1293 -
194.1294 -    // By here, "options" is always non-null
194.1295 -    var writeFunction = options["write"],
194.1296 -        disposeWhenNodeIsRemoved = options["disposeWhenNodeIsRemoved"] || options.disposeWhenNodeIsRemoved || null,
194.1297 -        disposeWhen = options["disposeWhen"] || options.disposeWhen || function() { return false; },
194.1298 -        dispose = disposeAllSubscriptionsToDependencies,
194.1299 -        _subscriptionsToDependencies = [],
194.1300 -        evaluationTimeoutInstance = null;
194.1301 -
194.1302 -    if (!evaluatorFunctionTarget)
194.1303 -        evaluatorFunctionTarget = options["owner"];
194.1304 -
194.1305 -    dependentObservable.peek = peek;
194.1306 -    dependentObservable.getDependenciesCount = function () { return _subscriptionsToDependencies.length; };
194.1307 -    dependentObservable.hasWriteFunction = typeof options["write"] === "function";
194.1308 -    dependentObservable.dispose = function () { dispose(); };
194.1309 -    dependentObservable.isActive = isActive;
194.1310 -    dependentObservable.valueHasMutated = function() {
194.1311 -        _hasBeenEvaluated = false;
194.1312 -        evaluateImmediate();
194.1313 -    };
194.1314 -
194.1315 -    ko.subscribable.call(dependentObservable);
194.1316 -    ko.utils.extend(dependentObservable, ko.dependentObservable['fn']);
194.1317 -
194.1318 -    ko.exportProperty(dependentObservable, 'peek', dependentObservable.peek);
194.1319 -    ko.exportProperty(dependentObservable, 'dispose', dependentObservable.dispose);
194.1320 -    ko.exportProperty(dependentObservable, 'isActive', dependentObservable.isActive);
194.1321 -    ko.exportProperty(dependentObservable, 'getDependenciesCount', dependentObservable.getDependenciesCount);
194.1322 -
194.1323 -    // Evaluate, unless deferEvaluation is true
194.1324 -    if (options['deferEvaluation'] !== true)
194.1325 -        evaluateImmediate();
194.1326 -
194.1327 -    // Build "disposeWhenNodeIsRemoved" and "disposeWhenNodeIsRemovedCallback" option values.
194.1328 -    // But skip if isActive is false (there will never be any dependencies to dispose).
194.1329 -    // (Note: "disposeWhenNodeIsRemoved" option both proactively disposes as soon as the node is removed using ko.removeNode(),
194.1330 -    // plus adds a "disposeWhen" callback that, on each evaluation, disposes if the node was removed by some other means.)
194.1331 -    if (disposeWhenNodeIsRemoved && isActive()) {
194.1332 -        dispose = function() {
194.1333 -            ko.utils.domNodeDisposal.removeDisposeCallback(disposeWhenNodeIsRemoved, arguments.callee);
194.1334 -            disposeAllSubscriptionsToDependencies();
194.1335 -        };
194.1336 -        ko.utils.domNodeDisposal.addDisposeCallback(disposeWhenNodeIsRemoved, dispose);
194.1337 -        var existingDisposeWhenFunction = disposeWhen;
194.1338 -        disposeWhen = function () {
194.1339 -            return !ko.utils.domNodeIsAttachedToDocument(disposeWhenNodeIsRemoved) || existingDisposeWhenFunction();
194.1340 -        }
194.1341 -    }
194.1342 -
194.1343 -    return dependentObservable;
194.1344 -};
194.1345 -
194.1346 -ko.isComputed = function(instance) {
194.1347 -    return ko.hasPrototype(instance, ko.dependentObservable);
194.1348 -};
194.1349 -
194.1350 -var protoProp = ko.observable.protoProperty; // == "__ko_proto__"
194.1351 -ko.dependentObservable[protoProp] = ko.observable;
194.1352 -
194.1353 -ko.dependentObservable['fn'] = {};
194.1354 -ko.dependentObservable['fn'][protoProp] = ko.dependentObservable;
194.1355 -
194.1356 -ko.exportSymbol('dependentObservable', ko.dependentObservable);
194.1357 -ko.exportSymbol('computed', ko.dependentObservable); // Make "ko.computed" an alias for "ko.dependentObservable"
194.1358 -ko.exportSymbol('isComputed', ko.isComputed);
194.1359 -
194.1360 -(function() {
194.1361 -    var maxNestedObservableDepth = 10; // Escape the (unlikely) pathalogical case where an observable's current value is itself (or similar reference cycle)
194.1362 -
194.1363 -    ko.toJS = function(rootObject) {
194.1364 -        if (arguments.length == 0)
194.1365 -            throw new Error("When calling ko.toJS, pass the object you want to convert.");
194.1366 -
194.1367 -        // We just unwrap everything at every level in the object graph
194.1368 -        return mapJsObjectGraph(rootObject, function(valueToMap) {
194.1369 -            // Loop because an observable's value might in turn be another observable wrapper
194.1370 -            for (var i = 0; ko.isObservable(valueToMap) && (i < maxNestedObservableDepth); i++)
194.1371 -                valueToMap = valueToMap();
194.1372 -            return valueToMap;
194.1373 -        });
194.1374 -    };
194.1375 -
194.1376 -    ko.toJSON = function(rootObject, replacer, space) {     // replacer and space are optional
194.1377 -        var plainJavaScriptObject = ko.toJS(rootObject);
194.1378 -        return ko.utils.stringifyJson(plainJavaScriptObject, replacer, space);
194.1379 -    };
194.1380 -
194.1381 -    function mapJsObjectGraph(rootObject, mapInputCallback, visitedObjects) {
194.1382 -        visitedObjects = visitedObjects || new objectLookup();
194.1383 -
194.1384 -        rootObject = mapInputCallback(rootObject);
194.1385 -        var canHaveProperties = (typeof rootObject == "object") && (rootObject !== null) && (rootObject !== undefined) && (!(rootObject instanceof Date));
194.1386 -        if (!canHaveProperties)
194.1387 -            return rootObject;
194.1388 -
194.1389 -        var outputProperties = rootObject instanceof Array ? [] : {};
194.1390 -        visitedObjects.save(rootObject, outputProperties);
194.1391 -
194.1392 -        visitPropertiesOrArrayEntries(rootObject, function(indexer) {
194.1393 -            var propertyValue = mapInputCallback(rootObject[indexer]);
194.1394 -
194.1395 -            switch (typeof propertyValue) {
194.1396 -                case "boolean":
194.1397 -                case "number":
194.1398 -                case "string":
194.1399 -                case "function":
194.1400 -                    outputProperties[indexer] = propertyValue;
194.1401 -                    break;
194.1402 -                case "object":
194.1403 -                case "undefined":
194.1404 -                    var previouslyMappedValue = visitedObjects.get(propertyValue);
194.1405 -                    outputProperties[indexer] = (previouslyMappedValue !== undefined)
194.1406 -                        ? previouslyMappedValue
194.1407 -                        : mapJsObjectGraph(propertyValue, mapInputCallback, visitedObjects);
194.1408 -                    break;
194.1409 -            }
194.1410 -        });
194.1411 -
194.1412 -        return outputProperties;
194.1413 -    }
194.1414 -
194.1415 -    function visitPropertiesOrArrayEntries(rootObject, visitorCallback) {
194.1416 -        if (rootObject instanceof Array) {
194.1417 -            for (var i = 0; i < rootObject.length; i++)
194.1418 -                visitorCallback(i);
194.1419 -
194.1420 -            // For arrays, also respect toJSON property for custom mappings (fixes #278)
194.1421 -            if (typeof rootObject['toJSON'] == 'function')
194.1422 -                visitorCallback('toJSON');
194.1423 -        } else {
194.1424 -            for (var propertyName in rootObject)
194.1425 -                visitorCallback(propertyName);
194.1426 -        }
194.1427 -    };
194.1428 -
194.1429 -    function objectLookup() {
194.1430 -        var keys = [];
194.1431 -        var values = [];
194.1432 -        this.save = function(key, value) {
194.1433 -            var existingIndex = ko.utils.arrayIndexOf(keys, key);
194.1434 -            if (existingIndex >= 0)
194.1435 -                values[existingIndex] = value;
194.1436 -            else {
194.1437 -                keys.push(key);
194.1438 -                values.push(value);
194.1439 -            }
194.1440 -        };
194.1441 -        this.get = function(key) {
194.1442 -            var existingIndex = ko.utils.arrayIndexOf(keys, key);
194.1443 -            return (existingIndex >= 0) ? values[existingIndex] : undefined;
194.1444 -        };
194.1445 -    };
194.1446 -})();
194.1447 -
194.1448 -ko.exportSymbol('toJS', ko.toJS);
194.1449 -ko.exportSymbol('toJSON', ko.toJSON);
194.1450 -(function () {
194.1451 -    var hasDomDataExpandoProperty = '__ko__hasDomDataOptionValue__';
194.1452 -
194.1453 -    // Normally, SELECT elements and their OPTIONs can only take value of type 'string' (because the values
194.1454 -    // are stored on DOM attributes). ko.selectExtensions provides a way for SELECTs/OPTIONs to have values
194.1455 -    // that are arbitrary objects. This is very convenient when implementing things like cascading dropdowns.
194.1456 -    ko.selectExtensions = {
194.1457 -        readValue : function(element) {
194.1458 -            switch (ko.utils.tagNameLower(element)) {
194.1459 -                case 'option':
194.1460 -                    if (element[hasDomDataExpandoProperty] === true)
194.1461 -                        return ko.utils.domData.get(element, ko.bindingHandlers.options.optionValueDomDataKey);
194.1462 -                    return ko.utils.ieVersion <= 7
194.1463 -                        ? (element.getAttributeNode('value').specified ? element.value : element.text)
194.1464 -                        : element.value;
194.1465 -                case 'select':
194.1466 -                    return element.selectedIndex >= 0 ? ko.selectExtensions.readValue(element.options[element.selectedIndex]) : undefined;
194.1467 -                default:
194.1468 -                    return element.value;
194.1469 -            }
194.1470 -        },
194.1471 -
194.1472 -        writeValue: function(element, value) {
194.1473 -            switch (ko.utils.tagNameLower(element)) {
194.1474 -                case 'option':
194.1475 -                    switch(typeof value) {
194.1476 -                        case "string":
194.1477 -                            ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, undefined);
194.1478 -                            if (hasDomDataExpandoProperty in element) { // IE <= 8 throws errors if you delete non-existent properties from a DOM node
194.1479 -                                delete element[hasDomDataExpandoProperty];
194.1480 -                            }
194.1481 -                            element.value = value;
194.1482 -                            break;
194.1483 -                        default:
194.1484 -                            // Store arbitrary object using DomData
194.1485 -                            ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, value);
194.1486 -                            element[hasDomDataExpandoProperty] = true;
194.1487 -
194.1488 -                            // Special treatment of numbers is just for backward compatibility. KO 1.2.1 wrote numerical values to element.value.
194.1489 -                            element.value = typeof value === "number" ? value : "";
194.1490 -                            break;
194.1491 -                    }
194.1492 -                    break;
194.1493 -                case 'select':
194.1494 -                    for (var i = element.options.length - 1; i >= 0; i--) {
194.1495 -                        if (ko.selectExtensions.readValue(element.options[i]) == value) {
194.1496 -                            element.selectedIndex = i;
194.1497 -                            break;
194.1498 -                        }
194.1499 -                    }
194.1500 -                    break;
194.1501 -                default:
194.1502 -                    if ((value === null) || (value === undefined))
194.1503 -                        value = "";
194.1504 -                    element.value = value;
194.1505 -                    break;
194.1506 -            }
194.1507 -        }
194.1508 -    };
194.1509 -})();
194.1510 -
194.1511 -ko.exportSymbol('selectExtensions', ko.selectExtensions);
194.1512 -ko.exportSymbol('selectExtensions.readValue', ko.selectExtensions.readValue);
194.1513 -ko.exportSymbol('selectExtensions.writeValue', ko.selectExtensions.writeValue);
194.1514 -ko.expressionRewriting = (function () {
194.1515 -    var restoreCapturedTokensRegex = /\@ko_token_(\d+)\@/g;
194.1516 -    var javaScriptReservedWords = ["true", "false"];
194.1517 -
194.1518 -    // Matches something that can be assigned to--either an isolated identifier or something ending with a property accessor
194.1519 -    // This is designed to be simple and avoid false negatives, but could produce false positives (e.g., a+b.c).
194.1520 -    var javaScriptAssignmentTarget = /^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i;
194.1521 -
194.1522 -    function restoreTokens(string, tokens) {
194.1523 -        var prevValue = null;
194.1524 -        while (string != prevValue) { // Keep restoring tokens until it no longer makes a difference (they may be nested)
194.1525 -            prevValue = string;
194.1526 -            string = string.replace(restoreCapturedTokensRegex, function (match, tokenIndex) {
194.1527 -                return tokens[tokenIndex];
194.1528 -            });
194.1529 -        }
194.1530 -        return string;
194.1531 -    }
194.1532 -
194.1533 -    function getWriteableValue(expression) {
194.1534 -        if (ko.utils.arrayIndexOf(javaScriptReservedWords, ko.utils.stringTrim(expression).toLowerCase()) >= 0)
194.1535 -            return false;
194.1536 -        var match = expression.match(javaScriptAssignmentTarget);
194.1537 -        return match === null ? false : match[1] ? ('Object(' + match[1] + ')' + match[2]) : expression;
194.1538 -    }
194.1539 -
194.1540 -    function ensureQuoted(key) {
194.1541 -        var trimmedKey = ko.utils.stringTrim(key);
194.1542 -        switch (trimmedKey.length && trimmedKey.charAt(0)) {
194.1543 -            case "'":
194.1544 -            case '"':
194.1545 -                return key;
194.1546 -            default:
194.1547 -                return "'" + trimmedKey + "'";
194.1548 -        }
194.1549 -    }
194.1550 -
194.1551 -    return {
194.1552 -        bindingRewriteValidators: [],
194.1553 -
194.1554 -        parseObjectLiteral: function(objectLiteralString) {
194.1555 -            // A full tokeniser+lexer would add too much weight to this library, so here's a simple parser
194.1556 -            // that is sufficient just to split an object literal string into a set of top-level key-value pairs
194.1557 -
194.1558 -            var str = ko.utils.stringTrim(objectLiteralString);
194.1559 -            if (str.length < 3)
194.1560 -                return [];
194.1561 -            if (str.charAt(0) === "{")// Ignore any braces surrounding the whole object literal
194.1562 -                str = str.substring(1, str.length - 1);
194.1563 -
194.1564 -            // Pull out any string literals and regex literals
194.1565 -            var tokens = [];
194.1566 -            var tokenStart = null, tokenEndChar;
194.1567 -            for (var position = 0; position < str.length; position++) {
194.1568 -                var c = str.charAt(position);
194.1569 -                if (tokenStart === null) {
194.1570 -                    switch (c) {
194.1571 -                        case '"':
194.1572 -                        case "'":
194.1573 -                        case "/":
194.1574 -                            tokenStart = position;
194.1575 -                            tokenEndChar = c;
194.1576 -                            break;
194.1577 -                    }
194.1578 -                } else if ((c == tokenEndChar) && (str.charAt(position - 1) !== "\\")) {
194.1579 -                    var token = str.substring(tokenStart, position + 1);
194.1580 -                    tokens.push(token);
194.1581 -                    var replacement = "@ko_token_" + (tokens.length - 1) + "@";
194.1582 -                    str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
194.1583 -                    position -= (token.length - replacement.length);
194.1584 -                    tokenStart = null;
194.1585 -                }
194.1586 -            }
194.1587 -
194.1588 -            // Next pull out balanced paren, brace, and bracket blocks
194.1589 -            tokenStart = null;
194.1590 -            tokenEndChar = null;
194.1591 -            var tokenDepth = 0, tokenStartChar = null;
194.1592 -            for (var position = 0; position < str.length; position++) {
194.1593 -                var c = str.charAt(position);
194.1594 -                if (tokenStart === null) {
194.1595 -                    switch (c) {
194.1596 -                        case "{": tokenStart = position; tokenStartChar = c;
194.1597 -                                  tokenEndChar = "}";
194.1598 -                                  break;
194.1599 -                        case "(": tokenStart = position; tokenStartChar = c;
194.1600 -                                  tokenEndChar = ")";
194.1601 -                                  break;
194.1602 -                        case "[": tokenStart = position; tokenStartChar = c;
194.1603 -                                  tokenEndChar = "]";
194.1604 -                                  break;
194.1605 -                    }
194.1606 -                }
194.1607 -
194.1608 -                if (c === tokenStartChar)
194.1609 -                    tokenDepth++;
194.1610 -                else if (c === tokenEndChar) {
194.1611 -                    tokenDepth--;
194.1612 -                    if (tokenDepth === 0) {
194.1613 -                        var token = str.substring(tokenStart, position + 1);
194.1614 -                        tokens.push(token);
194.1615 -                        var replacement = "@ko_token_" + (tokens.length - 1) + "@";
194.1616 -                        str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
194.1617 -                        position -= (token.length - replacement.length);
194.1618 -                        tokenStart = null;
194.1619 -                    }
194.1620 -                }
194.1621 -            }
194.1622 -
194.1623 -            // Now we can safely split on commas to get the key/value pairs
194.1624 -            var result = [];
194.1625 -            var keyValuePairs = str.split(",");
194.1626 -            for (var i = 0, j = keyValuePairs.length; i < j; i++) {
194.1627 -                var pair = keyValuePairs[i];
194.1628 -                var colonPos = pair.indexOf(":");
194.1629 -                if ((colonPos > 0) && (colonPos < pair.length - 1)) {
194.1630 -                    var key = pair.substring(0, colonPos);
194.1631 -                    var value = pair.substring(colonPos + 1);
194.1632 -                    result.push({ 'key': restoreTokens(key, tokens), 'value': restoreTokens(value, tokens) });
194.1633 -                } else {
194.1634 -                    result.push({ 'unknown': restoreTokens(pair, tokens) });
194.1635 -                }
194.1636 -            }
194.1637 -            return result;
194.1638 -        },
194.1639 -
194.1640 -        preProcessBindings: function (objectLiteralStringOrKeyValueArray) {
194.1641 -            var keyValueArray = typeof objectLiteralStringOrKeyValueArray === "string"
194.1642 -                ? ko.expressionRewriting.parseObjectLiteral(objectLiteralStringOrKeyValueArray)
194.1643 -                : objectLiteralStringOrKeyValueArray;
194.1644 -            var resultStrings = [], propertyAccessorResultStrings = [];
194.1645 -
194.1646 -            var keyValueEntry;
194.1647 -            for (var i = 0; keyValueEntry = keyValueArray[i]; i++) {
194.1648 -                if (resultStrings.length > 0)
194.1649 -                    resultStrings.push(",");
194.1650 -
194.1651 -                if (keyValueEntry['key']) {
194.1652 -                    var quotedKey = ensureQuoted(keyValueEntry['key']), val = keyValueEntry['value'];
194.1653 -                    resultStrings.push(quotedKey);
194.1654 -                    resultStrings.push(":");
194.1655 -                    resultStrings.push(val);
194.1656 -
194.1657 -                    if (val = getWriteableValue(ko.utils.stringTrim(val))) {
194.1658 -                        if (propertyAccessorResultStrings.length > 0)
194.1659 -                            propertyAccessorResultStrings.push(", ");
194.1660 -                        propertyAccessorResultStrings.push(quotedKey + " : function(__ko_value) { " + val + " = __ko_value; }");
194.1661 -                    }
194.1662 -                } else if (keyValueEntry['unknown']) {
194.1663 -                    resultStrings.push(keyValueEntry['unknown']);
194.1664 -                }
194.1665 -            }
194.1666 -
194.1667 -            var combinedResult = resultStrings.join("");
194.1668 -            if (propertyAccessorResultStrings.length > 0) {
194.1669 -                var allPropertyAccessors = propertyAccessorResultStrings.join("");
194.1670 -                combinedResult = combinedResult + ", '_ko_property_writers' : { " + allPropertyAccessors + " } ";
194.1671 -            }
194.1672 -
194.1673 -            return combinedResult;
194.1674 -        },
194.1675 -
194.1676 -        keyValueArrayContainsKey: function(keyValueArray, key) {
194.1677 -            for (var i = 0; i < keyValueArray.length; i++)
194.1678 -                if (ko.utils.stringTrim(keyValueArray[i]['key']) == key)
194.1679 -                    return true;
194.1680 -            return false;
194.1681 -        },
194.1682 -
194.1683 -        // Internal, private KO utility for updating model properties from within bindings
194.1684 -        // property:            If the property being updated is (or might be) an observable, pass it here
194.1685 -        //                      If it turns out to be a writable observable, it will be written to directly
194.1686 -        // allBindingsAccessor: All bindings in the current execution context.
194.1687 -        //                      This will be searched for a '_ko_property_writers' property in case you're writing to a non-observable
194.1688 -        // key:                 The key identifying the property to be written. Example: for { hasFocus: myValue }, write to 'myValue' by specifying the key 'hasFocus'
194.1689 -        // value:               The value to be written
194.1690 -        // checkIfDifferent:    If true, and if the property being written is a writable observable, the value will only be written if
194.1691 -        //                      it is !== existing value on that writable observable
194.1692 -        writeValueToProperty: function(property, allBindingsAccessor, key, value, checkIfDifferent) {
194.1693 -            if (!property || !ko.isWriteableObservable(property)) {
194.1694 -                var propWriters = allBindingsAccessor()['_ko_property_writers'];
194.1695 -                if (propWriters && propWriters[key])
194.1696 -                    propWriters[key](value);
194.1697 -            } else if (!checkIfDifferent || property.peek() !== value) {
194.1698 -                property(value);
194.1699 -            }
194.1700 -        }
194.1701 -    };
194.1702 -})();
194.1703 -
194.1704 -ko.exportSymbol('expressionRewriting', ko.expressionRewriting);
194.1705 -ko.exportSymbol('expressionRewriting.bindingRewriteValidators', ko.expressionRewriting.bindingRewriteValidators);
194.1706 -ko.exportSymbol('expressionRewriting.parseObjectLiteral', ko.expressionRewriting.parseObjectLiteral);
194.1707 -ko.exportSymbol('expressionRewriting.preProcessBindings', ko.expressionRewriting.preProcessBindings);
194.1708 -
194.1709 -// For backward compatibility, define the following aliases. (Previously, these function names were misleading because
194.1710 -// they referred to JSON specifically, even though they actually work with arbitrary JavaScript object literal expressions.)
194.1711 -ko.exportSymbol('jsonExpressionRewriting', ko.expressionRewriting);
194.1712 -ko.exportSymbol('jsonExpressionRewriting.insertPropertyAccessorsIntoJson', ko.expressionRewriting.preProcessBindings);(function() {
194.1713 -    // "Virtual elements" is an abstraction on top of the usual DOM API which understands the notion that comment nodes
194.1714 -    // may be used to represent hierarchy (in addition to the DOM's natural hierarchy).
194.1715 -    // If you call the DOM-manipulating functions on ko.virtualElements, you will be able to read and write the state
194.1716 -    // of that virtual hierarchy
194.1717 -    //
194.1718 -    // The point of all this is to support containerless templates (e.g., <!-- ko foreach:someCollection -->blah<!-- /ko -->)
194.1719 -    // without having to scatter special cases all over the binding and templating code.
194.1720 -
194.1721 -    // IE 9 cannot reliably read the "nodeValue" property of a comment node (see https://github.com/SteveSanderson/knockout/issues/186)
194.1722 -    // but it does give them a nonstandard alternative property called "text" that it can read reliably. Other browsers don't have that property.
194.1723 -    // So, use node.text where available, and node.nodeValue elsewhere
194.1724 -    var commentNodesHaveTextProperty = document.createComment("test").text === "<!--test-->";
194.1725 -
194.1726 -    var startCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*-->$/ : /^\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*$/;
194.1727 -    var endCommentRegex =   commentNodesHaveTextProperty ? /^<!--\s*\/ko\s*-->$/ : /^\s*\/ko\s*$/;
194.1728 -    var htmlTagsWithOptionallyClosingChildren = { 'ul': true, 'ol': true };
194.1729 -
194.1730 -    function isStartComment(node) {
194.1731 -        return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(startCommentRegex);
194.1732 -    }
194.1733 -
194.1734 -    function isEndComment(node) {
194.1735 -        return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(endCommentRegex);
194.1736 -    }
194.1737 -
194.1738 -    function getVirtualChildren(startComment, allowUnbalanced) {
194.1739 -        var currentNode = startComment;
194.1740 -        var depth = 1;
194.1741 -        var children = [];
194.1742 -        while (currentNode = currentNode.nextSibling) {
194.1743 -            if (isEndComment(currentNode)) {
194.1744 -                depth--;
194.1745 -                if (depth === 0)
194.1746 -                    return children;
194.1747 -            }
194.1748 -
194.1749 -            children.push(currentNode);
194.1750 -
194.1751 -            if (isStartComment(currentNode))
194.1752 -                depth++;
194.1753 -        }
194.1754 -        if (!allowUnbalanced)
194.1755 -            throw new Error("Cannot find closing comment tag to match: " + startComment.nodeValue);
194.1756 -        return null;
194.1757 -    }
194.1758 -
194.1759 -    function getMatchingEndComment(startComment, allowUnbalanced) {
194.1760 -        var allVirtualChildren = getVirtualChildren(startComment, allowUnbalanced);
194.1761 -        if (allVirtualChildren) {
194.1762 -            if (allVirtualChildren.length > 0)
194.1763 -                return allVirtualChildren[allVirtualChildren.length - 1].nextSibling;
194.1764 -            return startComment.nextSibling;
194.1765 -        } else
194.1766 -            return null; // Must have no matching end comment, and allowUnbalanced is true
194.1767 -    }
194.1768 -
194.1769 -    function getUnbalancedChildTags(node) {
194.1770 -        // e.g., from <div>OK</div><!-- ko blah --><span>Another</span>, returns: <!-- ko blah --><span>Another</span>
194.1771 -        //       from <div>OK</div><!-- /ko --><!-- /ko -->,             returns: <!-- /ko --><!-- /ko -->
194.1772 -        var childNode = node.firstChild, captureRemaining = null;
194.1773 -        if (childNode) {
194.1774 -            do {
194.1775 -                if (captureRemaining)                   // We already hit an unbalanced node and are now just scooping up all subsequent nodes
194.1776 -                    captureRemaining.push(childNode);
194.1777 -                else if (isStartComment(childNode)) {
194.1778 -                    var matchingEndComment = getMatchingEndComment(childNode, /* allowUnbalanced: */ true);
194.1779 -                    if (matchingEndComment)             // It's a balanced tag, so skip immediately to the end of this virtual set
194.1780 -                        childNode = matchingEndComment;
194.1781 -                    else
194.1782 -                        captureRemaining = [childNode]; // It's unbalanced, so start capturing from this point
194.1783 -                } else if (isEndComment(childNode)) {
194.1784 -                    captureRemaining = [childNode];     // It's unbalanced (if it wasn't, we'd have skipped over it already), so start capturing
194.1785 -                }
194.1786 -            } while (childNode = childNode.nextSibling);
194.1787 -        }
194.1788 -        return captureRemaining;
194.1789 -    }
194.1790 -
194.1791 -    ko.virtualElements = {
194.1792 -        allowedBindings: {},
194.1793 -
194.1794 -        childNodes: function(node) {
194.1795 -            return isStartComment(node) ? getVirtualChildren(node) : node.childNodes;
194.1796 -        },
194.1797 -
194.1798 -        emptyNode: function(node) {
194.1799 -            if (!isStartComment(node))
194.1800 -                ko.utils.emptyDomNode(node);
194.1801 -            else {
194.1802 -                var virtualChildren = ko.virtualElements.childNodes(node);
194.1803 -                for (var i = 0, j = virtualChildren.length; i < j; i++)
194.1804 -                    ko.removeNode(virtualChildren[i]);
194.1805 -            }
194.1806 -        },
194.1807 -
194.1808 -        setDomNodeChildren: function(node, childNodes) {
194.1809 -            if (!isStartComment(node))
194.1810 -                ko.utils.setDomNodeChildren(node, childNodes);
194.1811 -            else {
194.1812 -                ko.virtualElements.emptyNode(node);
194.1813 -                var endCommentNode = node.nextSibling; // Must be the next sibling, as we just emptied the children
194.1814 -                for (var i = 0, j = childNodes.length; i < j; i++)
194.1815 -                    endCommentNode.parentNode.insertBefore(childNodes[i], endCommentNode);
194.1816 -            }
194.1817 -        },
194.1818 -
194.1819 -        prepend: function(containerNode, nodeToPrepend) {
194.1820 -            if (!isStartComment(containerNode)) {
194.1821 -                if (containerNode.firstChild)
194.1822 -                    containerNode.insertBefore(nodeToPrepend, containerNode.firstChild);
194.1823 -                else
194.1824 -                    containerNode.appendChild(nodeToPrepend);
194.1825 -            } else {
194.1826 -                // Start comments must always have a parent and at least one following sibling (the end comment)
194.1827 -                containerNode.parentNode.insertBefore(nodeToPrepend, containerNode.nextSibling);
194.1828 -            }
194.1829 -        },
194.1830 -
194.1831 -        insertAfter: function(containerNode, nodeToInsert, insertAfterNode) {
194.1832 -            if (!insertAfterNode) {
194.1833 -                ko.virtualElements.prepend(containerNode, nodeToInsert);
194.1834 -            } else if (!isStartComment(containerNode)) {
194.1835 -                // Insert after insertion point
194.1836 -                if (insertAfterNode.nextSibling)
194.1837 -                    containerNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
194.1838 -                else
194.1839 -                    containerNode.appendChild(nodeToInsert);
194.1840 -            } else {
194.1841 -                // Children of start comments must always have a parent and at least one following sibling (the end comment)
194.1842 -                containerNode.parentNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
194.1843 -            }
194.1844 -        },
194.1845 -
194.1846 -        firstChild: function(node) {
194.1847 -            if (!isStartComment(node))
194.1848 -                return node.firstChild;
194.1849 -            if (!node.nextSibling || isEndComment(node.nextSibling))
194.1850 -                return null;
194.1851 -            return node.nextSibling;
194.1852 -        },
194.1853 -
194.1854 -        nextSibling: function(node) {
194.1855 -            if (isStartComment(node))
194.1856 -                node = getMatchingEndComment(node);
194.1857 -            if (node.nextSibling && isEndComment(node.nextSibling))
194.1858 -                return null;
194.1859 -            return node.nextSibling;
194.1860 -        },
194.1861 -
194.1862 -        virtualNodeBindingValue: function(node) {
194.1863 -            var regexMatch = isStartComment(node);
194.1864 -            return regexMatch ? regexMatch[1] : null;
194.1865 -        },
194.1866 -
194.1867 -        normaliseVirtualElementDomStructure: function(elementVerified) {
194.1868 -            // Workaround for https://github.com/SteveSanderson/knockout/issues/155
194.1869 -            // (IE <= 8 or IE 9 quirks mode parses your HTML weirdly, treating closing </li> tags as if they don't exist, thereby moving comment nodes
194.1870 -            // that are direct descendants of <ul> into the preceding <li>)
194.1871 -            if (!htmlTagsWithOptionallyClosingChildren[ko.utils.tagNameLower(elementVerified)])
194.1872 -                return;
194.1873 -
194.1874 -            // Scan immediate children to see if they contain unbalanced comment tags. If they do, those comment tags
194.1875 -            // must be intended to appear *after* that child, so move them there.
194.1876 -            var childNode = elementVerified.firstChild;
194.1877 -            if (childNode) {
194.1878 -                do {
194.1879 -                    if (childNode.nodeType === 1) {
194.1880 -                        var unbalancedTags = getUnbalancedChildTags(childNode);
194.1881 -                        if (unbalancedTags) {
194.1882 -                            // Fix up the DOM by moving the unbalanced tags to where they most likely were intended to be placed - *after* the child
194.1883 -                            var nodeToInsertBefore = childNode.nextSibling;
194.1884 -                            for (var i = 0; i < unbalancedTags.length; i++) {
194.1885 -                                if (nodeToInsertBefore)
194.1886 -                                    elementVerified.insertBefore(unbalancedTags[i], nodeToInsertBefore);
194.1887 -                                else
194.1888 -                                    elementVerified.appendChild(unbalancedTags[i]);
194.1889 -                            }
194.1890 -                        }
194.1891 -                    }
194.1892 -                } while (childNode = childNode.nextSibling);
194.1893 -            }
194.1894 -        }
194.1895 -    };
194.1896 -})();
194.1897 -ko.exportSymbol('virtualElements', ko.virtualElements);
194.1898 -ko.exportSymbol('virtualElements.allowedBindings', ko.virtualElements.allowedBindings);
194.1899 -ko.exportSymbol('virtualElements.emptyNode', ko.virtualElements.emptyNode);
194.1900 -//ko.exportSymbol('virtualElements.firstChild', ko.virtualElements.firstChild);     // firstChild is not minified
194.1901 -ko.exportSymbol('virtualElements.insertAfter', ko.virtualElements.insertAfter);
194.1902 -//ko.exportSymbol('virtualElements.nextSibling', ko.virtualElements.nextSibling);   // nextSibling is not minified
194.1903 -ko.exportSymbol('virtualElements.prepend', ko.virtualElements.prepend);
194.1904 -ko.exportSymbol('virtualElements.setDomNodeChildren', ko.virtualElements.setDomNodeChildren);
194.1905 -(function() {
194.1906 -    var defaultBindingAttributeName = "data-bind";
194.1907 -
194.1908 -    ko.bindingProvider = function() {
194.1909 -        this.bindingCache = {};
194.1910 -    };
194.1911 -
194.1912 -    ko.utils.extend(ko.bindingProvider.prototype, {
194.1913 -        'nodeHasBindings': function(node) {
194.1914 -            switch (node.nodeType) {
194.1915 -                case 1: return node.getAttribute(defaultBindingAttributeName) != null;   // Element
194.1916 -                case 8: return ko.virtualElements.virtualNodeBindingValue(node) != null; // Comment node
194.1917 -                default: return false;
194.1918 -            }
194.1919 -        },
194.1920 -
194.1921 -        'getBindings': function(node, bindingContext) {
194.1922 -            var bindingsString = this['getBindingsString'](node, bindingContext);
194.1923 -            return bindingsString ? this['parseBindingsString'](bindingsString, bindingContext, node) : null;
194.1924 -        },
194.1925 -
194.1926 -        // The following function is only used internally by this default provider.
194.1927 -        // It's not part of the interface definition for a general binding provider.
194.1928 -        'getBindingsString': function(node, bindingContext) {
194.1929 -            switch (node.nodeType) {
194.1930 -                case 1: return node.getAttribute(defaultBindingAttributeName);   // Element
194.1931 -                case 8: return ko.virtualElements.virtualNodeBindingValue(node); // Comment node
194.1932 -                default: return null;
194.1933 -            }
194.1934 -        },
194.1935 -
194.1936 -        // The following function is only used internally by this default provider.
194.1937 -        // It's not part of the interface definition for a general binding provider.
194.1938 -        'parseBindingsString': function(bindingsString, bindingContext, node) {
194.1939 -            try {
194.1940 -                var bindingFunction = createBindingsStringEvaluatorViaCache(bindingsString, this.bindingCache);
194.1941 -                return bindingFunction(bindingContext, node);
194.1942 -            } catch (ex) {
194.1943 -                throw new Error("Unable to parse bindings.\nMessage: " + ex + ";\nBindings value: " + bindingsString);
194.1944 -            }
194.1945 -        }
194.1946 -    });
194.1947 -
194.1948 -    ko.bindingProvider['instance'] = new ko.bindingProvider();
194.1949 -
194.1950 -    function createBindingsStringEvaluatorViaCache(bindingsString, cache) {
194.1951 -        var cacheKey = bindingsString;
194.1952 -        return cache[cacheKey]
194.1953 -            || (cache[cacheKey] = createBindingsStringEvaluator(bindingsString));
194.1954 -    }
194.1955 -
194.1956 -    function createBindingsStringEvaluator(bindingsString) {
194.1957 -        // Build the source for a function that evaluates "expression"
194.1958 -        // For each scope variable, add an extra level of "with" nesting
194.1959 -        // Example result: with(sc1) { with(sc0) { return (expression) } }
194.1960 -        var rewrittenBindings = ko.expressionRewriting.preProcessBindings(bindingsString),
194.1961 -            functionBody = "with($context){with($data||{}){return{" + rewrittenBindings + "}}}";
194.1962 -        return new Function("$context", "$element", functionBody);
194.1963 -    }
194.1964 -})();
194.1965 -
194.1966 -ko.exportSymbol('bindingProvider', ko.bindingProvider);
194.1967 -(function () {
194.1968 -    ko.bindingHandlers = {};
194.1969 -
194.1970 -    ko.bindingContext = function(dataItem, parentBindingContext, dataItemAlias) {
194.1971 -        if (parentBindingContext) {
194.1972 -            ko.utils.extend(this, parentBindingContext); // Inherit $root and any custom properties
194.1973 -            this['$parentContext'] = parentBindingContext;
194.1974 -            this['$parent'] = parentBindingContext['$data'];
194.1975 -            this['$parents'] = (parentBindingContext['$parents'] || []).slice(0);
194.1976 -            this['$parents'].unshift(this['$parent']);
194.1977 -        } else {
194.1978 -            this['$parents'] = [];
194.1979 -            this['$root'] = dataItem;
194.1980 -            // Export 'ko' in the binding context so it will be available in bindings and templates
194.1981 -            // even if 'ko' isn't exported as a global, such as when using an AMD loader.
194.1982 -            // See https://github.com/SteveSanderson/knockout/issues/490
194.1983 -            this['ko'] = ko;
194.1984 -        }
194.1985 -        this['$data'] = dataItem;
194.1986 -        if (dataItemAlias)
194.1987 -            this[dataItemAlias] = dataItem;
194.1988 -    }
194.1989 -    ko.bindingContext.prototype['createChildContext'] = function (dataItem, dataItemAlias) {
194.1990 -        return new ko.bindingContext(dataItem, this, dataItemAlias);
194.1991 -    };
194.1992 -    ko.bindingContext.prototype['extend'] = function(properties) {
194.1993 -        var clone = ko.utils.extend(new ko.bindingContext(), this);
194.1994 -        return ko.utils.extend(clone, properties);
194.1995 -    };
194.1996 -
194.1997 -    function validateThatBindingIsAllowedForVirtualElements(bindingName) {
194.1998 -        var validator = ko.virtualElements.allowedBindings[bindingName];
194.1999 -        if (!validator)
194.2000 -            throw new Error("The binding '" + bindingName + "' cannot be used with virtual elements")
194.2001 -    }
194.2002 -
194.2003 -    function applyBindingsToDescendantsInternal (viewModel, elementOrVirtualElement, bindingContextsMayDifferFromDomParentElement) {
194.2004 -        var currentChild, nextInQueue = ko.virtualElements.firstChild(elementOrVirtualElement);
194.2005 -        while (currentChild = nextInQueue) {
194.2006 -            // Keep a record of the next child *before* applying bindings, in case the binding removes the current child from its position
194.2007 -            nextInQueue = ko.virtualElements.nextSibling(currentChild);
194.2008 -            applyBindingsToNodeAndDescendantsInternal(viewModel, currentChild, bindingContextsMayDifferFromDomParentElement);
194.2009 -        }
194.2010 -    }
194.2011 -
194.2012 -    function applyBindingsToNodeAndDescendantsInternal (viewModel, nodeVerified, bindingContextMayDifferFromDomParentElement) {
194.2013 -        var shouldBindDescendants = true;
194.2014 -
194.2015 -        // Perf optimisation: Apply bindings only if...
194.2016 -        // (1) We need to store the binding context on this node (because it may differ from the DOM parent node's binding context)
194.2017 -        //     Note that we can't store binding contexts on non-elements (e.g., text nodes), as IE doesn't allow expando properties for those
194.2018 -        // (2) It might have bindings (e.g., it has a data-bind attribute, or it's a marker for a containerless template)
194.2019 -        var isElement = (nodeVerified.nodeType === 1);
194.2020 -        if (isElement) // Workaround IE <= 8 HTML parsing weirdness
194.2021 -            ko.virtualElements.normaliseVirtualElementDomStructure(nodeVerified);
194.2022 -
194.2023 -        var shouldApplyBindings = (isElement && bindingContextMayDifferFromDomParentElement)             // Case (1)
194.2024 -                               || ko.bindingProvider['instance']['nodeHasBindings'](nodeVerified);       // Case (2)
194.2025 -        if (shouldApplyBindings)
194.2026 -            shouldBindDescendants = applyBindingsToNodeInternal(nodeVerified, null, viewModel, bindingContextMayDifferFromDomParentElement).shouldBindDescendants;
194.2027 -
194.2028 -        if (shouldBindDescendants) {
194.2029 -            // We're recursing automatically into (real or virtual) child nodes without changing binding contexts. So,
194.2030 -            //  * For children of a *real* element, the binding context is certainly the same as on their DOM .parentNode,
194.2031 -            //    hence bindingContextsMayDifferFromDomParentElement is false
194.2032 -            //  * For children of a *virtual* element, we can't be sure. Evaluating .parentNode on those children may
194.2033 -            //    skip over any number of intermediate virtual elements, any of which might define a custom binding context,
194.2034 -            //    hence bindingContextsMayDifferFromDomParentElement is true
194.2035 -            applyBindingsToDescendantsInternal(viewModel, nodeVerified, /* bindingContextsMayDifferFromDomParentElement: */ !isElement);
194.2036 -        }
194.2037 -    }
194.2038 -
194.2039 -    function applyBindingsToNodeInternal (node, bindings, viewModelOrBindingContext, bindingContextMayDifferFromDomParentElement) {
194.2040 -        // Need to be sure that inits are only run once, and updates never run until all the inits have been run
194.2041 -        var initPhase = 0; // 0 = before all inits, 1 = during inits, 2 = after all inits
194.2042 -
194.2043 -        // Each time the dependentObservable is evaluated (after data changes),
194.2044 -        // the binding attribute is reparsed so that it can pick out the correct
194.2045 -        // model properties in the context of the changed data.
194.2046 -        // DOM event callbacks need to be able to access this changed data,
194.2047 -        // so we need a single parsedBindings variable (shared by all callbacks
194.2048 -        // associated with this node's bindings) that all the closures can access.
194.2049 -        var parsedBindings;
194.2050 -        function makeValueAccessor(bindingKey) {
194.2051 -            return function () { return parsedBindings[bindingKey] }
194.2052 -        }
194.2053 -        function parsedBindingsAccessor() {
194.2054 -            return parsedBindings;
194.2055 -        }
194.2056 -
194.2057 -        var bindingHandlerThatControlsDescendantBindings;
194.2058 -        ko.dependentObservable(
194.2059 -            function () {
194.2060 -                // Ensure we have a nonnull binding context to work with
194.2061 -                var bindingContextInstance = viewModelOrBindingContext && (viewModelOrBindingContext instanceof ko.bindingContext)
194.2062 -                    ? viewModelOrBindingContext
194.2063 -                    : new ko.bindingContext(ko.utils.unwrapObservable(viewModelOrBindingContext));
194.2064 -                var viewModel = bindingContextInstance['$data'];
194.2065 -
194.2066 -                // Optimization: Don't store the binding context on this node if it's definitely the same as on node.parentNode, because
194.2067 -                // we can easily recover it just by scanning up the node's ancestors in the DOM
194.2068 -                // (note: here, parent node means "real DOM parent" not "virtual parent", as there's no O(1) way to find the virtual parent)
194.2069 -                if (bindingContextMayDifferFromDomParentElement)
194.2070 -                    ko.storedBindingContextForNode(node, bindingContextInstance);
194.2071 -
194.2072 -                // Use evaluatedBindings if given, otherwise fall back on asking the bindings provider to give us some bindings
194.2073 -                var evaluatedBindings = (typeof bindings == "function") ? bindings(bindingContextInstance, node) : bindings;
194.2074 -                parsedBindings = evaluatedBindings || ko.bindingProvider['instance']['getBindings'](node, bindingContextInstance);
194.2075 -
194.2076 -                if (parsedBindings) {
194.2077 -                    // First run all the inits, so bindings can register for notification on changes
194.2078 -                    if (initPhase === 0) {
194.2079 -                        initPhase = 1;
194.2080 -                        for (var bindingKey in parsedBindings) {
194.2081 -                            var binding = ko.bindingHandlers[bindingKey];
194.2082 -                            if (binding && node.nodeType === 8)
194.2083 -                                validateThatBindingIsAllowedForVirtualElements(bindingKey);
194.2084 -
194.2085 -                            if (binding && typeof binding["init"] == "function") {
194.2086 -                                var handlerInitFn = binding["init"];
194.2087 -                                var initResult = handlerInitFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
194.2088 -
194.2089 -                                // If this binding handler claims to control descendant bindings, make a note of this
194.2090 -                                if (initResult && initResult['controlsDescendantBindings']) {
194.2091 -                                    if (bindingHandlerThatControlsDescendantBindings !== undefined)
194.2092 -                                        throw new Error("Multiple bindings (" + bindingHandlerThatControlsDescendantBindings + " and " + bindingKey + ") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.");
194.2093 -                                    bindingHandlerThatControlsDescendantBindings = bindingKey;
194.2094 -                                }
194.2095 -                            }
194.2096 -                        }
194.2097 -                        initPhase = 2;
194.2098 -                    }
194.2099 -
194.2100 -                    // ... then run all the updates, which might trigger changes even on the first evaluation
194.2101 -                    if (initPhase === 2) {
194.2102 -                        for (var bindingKey in parsedBindings) {
194.2103 -                            var binding = ko.bindingHandlers[bindingKey];
194.2104 -                            if (binding && typeof binding["update"] == "function") {
194.2105 -                                var handlerUpdateFn = binding["update"];
194.2106 -                                handlerUpdateFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
194.2107 -                            }
194.2108 -                        }
194.2109 -                    }
194.2110 -                }
194.2111 -            },
194.2112 -            null,
194.2113 -            { disposeWhenNodeIsRemoved : node }
194.2114 -        );
194.2115 -
194.2116 -        return {
194.2117 -            shouldBindDescendants: bindingHandlerThatControlsDescendantBindings === undefined
194.2118 -        };
194.2119 -    };
194.2120 -
194.2121 -    var storedBindingContextDomDataKey = "__ko_bindingContext__";
194.2122 -    ko.storedBindingContextForNode = function (node, bindingContext) {
194.2123 -        if (arguments.length == 2)
194.2124 -            ko.utils.domData.set(node, storedBindingContextDomDataKey, bindingContext);
194.2125 -        else
194.2126 -            return ko.utils.domData.get(node, storedBindingContextDomDataKey);
194.2127 -    }
194.2128 -
194.2129 -    ko.applyBindingsToNode = function (node, bindings, viewModel) {
194.2130 -        if (node.nodeType === 1) // If it's an element, workaround IE <= 8 HTML parsing weirdness
194.2131 -            ko.virtualElements.normaliseVirtualElementDomStructure(node);
194.2132 -        return applyBindingsToNodeInternal(node, bindings, viewModel, true);
194.2133 -    };
194.2134 -
194.2135 -    ko.applyBindingsToDescendants = function(viewModel, rootNode) {
194.2136 -        if (rootNode.nodeType === 1 || rootNode.nodeType === 8)
194.2137 -            applyBindingsToDescendantsInternal(viewModel, rootNode, true);
194.2138 -    };
194.2139 -
194.2140 -    ko.applyBindings = function (viewModel, rootNode) {
194.2141 -        if (rootNode && (rootNode.nodeType !== 1) && (rootNode.nodeType !== 8))
194.2142 -            throw new Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");
194.2143 -        rootNode = rootNode || window.document.body; // Make "rootNode" parameter optional
194.2144 -
194.2145 -        applyBindingsToNodeAndDescendantsInternal(viewModel, rootNode, true);
194.2146 -    };
194.2147 -
194.2148 -    // Retrieving binding context from arbitrary nodes
194.2149 -    ko.contextFor = function(node) {
194.2150 -        // We can only do something meaningful for elements and comment nodes (in particular, not text nodes, as IE can't store domdata for them)
194.2151 -        switch (node.nodeType) {
194.2152 -            case 1:
194.2153 -            case 8:
194.2154 -                var context = ko.storedBindingContextForNode(node);
194.2155 -                if (context) return context;
194.2156 -                if (node.parentNode) return ko.contextFor(node.parentNode);
194.2157 -                break;
194.2158 -        }
194.2159 -        return undefined;
194.2160 -    };
194.2161 -    ko.dataFor = function(node) {
194.2162 -        var context = ko.contextFor(node);
194.2163 -        return context ? context['$data'] : undefined;
194.2164 -    };
194.2165 -
194.2166 -    ko.exportSymbol('bindingHandlers', ko.bindingHandlers);
194.2167 -    ko.exportSymbol('applyBindings', ko.applyBindings);
194.2168 -    ko.exportSymbol('applyBindingsToDescendants', ko.applyBindingsToDescendants);
194.2169 -    ko.exportSymbol('applyBindingsToNode', ko.applyBindingsToNode);
194.2170 -    ko.exportSymbol('contextFor', ko.contextFor);
194.2171 -    ko.exportSymbol('dataFor', ko.dataFor);
194.2172 -})();
194.2173 -var attrHtmlToJavascriptMap = { 'class': 'className', 'for': 'htmlFor' };
194.2174 -ko.bindingHandlers['attr'] = {
194.2175 -    'update': function(element, valueAccessor, allBindingsAccessor) {
194.2176 -        var value = ko.utils.unwrapObservable(valueAccessor()) || {};
194.2177 -        for (var attrName in value) {
194.2178 -            if (typeof attrName == "string") {
194.2179 -                var attrValue = ko.utils.unwrapObservable(value[attrName]);
194.2180 -
194.2181 -                // To cover cases like "attr: { checked:someProp }", we want to remove the attribute entirely
194.2182 -                // when someProp is a "no value"-like value (strictly null, false, or undefined)
194.2183 -                // (because the absence of the "checked" attr is how to mark an element as not checked, etc.)
194.2184 -                var toRemove = (attrValue === false) || (attrValue === null) || (attrValue === undefined);
194.2185 -                if (toRemove)
194.2186 -                    element.removeAttribute(attrName);
194.2187 -
194.2188 -                // In IE <= 7 and IE8 Quirks Mode, you have to use the Javascript property name instead of the
194.2189 -                // HTML attribute name for certain attributes. IE8 Standards Mode supports the correct behavior,
194.2190 -                // but instead of figuring out the mode, we'll just set the attribute through the Javascript
194.2191 -                // property for IE <= 8.
194.2192 -                if (ko.utils.ieVersion <= 8 && attrName in attrHtmlToJavascriptMap) {
194.2193 -                    attrName = attrHtmlToJavascriptMap[attrName];
194.2194 -                    if (toRemove)
194.2195 -                        element.removeAttribute(attrName);
194.2196 -                    else
194.2197 -                        element[attrName] = attrValue;
194.2198 -                } else if (!toRemove) {
194.2199 -                    try {
194.2200 -                        element.setAttribute(attrName, attrValue.toString());
194.2201 -                    } catch (err) {
194.2202 -                        // ignore for now
194.2203 -                        if (console) {
194.2204 -                            console.log("Can't set attribute " + attrName + " to " + attrValue + " error: " + err);
194.2205 -                        }
194.2206 -                    }
194.2207 -                }
194.2208 -
194.2209 -                // Treat "name" specially - although you can think of it as an attribute, it also needs
194.2210 -                // special handling on older versions of IE (https://github.com/SteveSanderson/knockout/pull/333)
194.2211 -                // Deliberately being case-sensitive here because XHTML would regard "Name" as a different thing
194.2212 -                // entirely, and there's no strong reason to allow for such casing in HTML.
194.2213 -                if (attrName === "name") {
194.2214 -                    ko.utils.setElementName(element, toRemove ? "" : attrValue.toString());
194.2215 -                }
194.2216 -            }
194.2217 -        }
194.2218 -    }
194.2219 -};
194.2220 -ko.bindingHandlers['checked'] = {
194.2221 -    'init': function (element, valueAccessor, allBindingsAccessor) {
194.2222 -        var updateHandler = function() {
194.2223 -            var valueToWrite;
194.2224 -            if (element.type == "checkbox") {
194.2225 -                valueToWrite = element.checked;
194.2226 -            } else if ((element.type == "radio") && (element.checked)) {
194.2227 -                valueToWrite = element.value;
194.2228 -            } else {
194.2229 -                return; // "checked" binding only responds to checkboxes and selected radio buttons
194.2230 -            }
194.2231 -
194.2232 -            var modelValue = valueAccessor(), unwrappedValue = ko.utils.unwrapObservable(modelValue);
194.2233 -            if ((element.type == "checkbox") && (unwrappedValue instanceof Array)) {
194.2234 -                // For checkboxes bound to an array, we add/remove the checkbox value to that array
194.2235 -                // This works for both observable and non-observable arrays
194.2236 -                var existingEntryIndex = ko.utils.arrayIndexOf(unwrappedValue, element.value);
194.2237 -                if (element.checked && (existingEntryIndex < 0))
194.2238 -                    modelValue.push(element.value);
194.2239 -                else if ((!element.checked) && (existingEntryIndex >= 0))
194.2240 -                    modelValue.splice(existingEntryIndex, 1);
194.2241 -            } else {
194.2242 -                ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'checked', valueToWrite, true);
194.2243 -            }
194.2244 -        };
194.2245 -        ko.utils.registerEventHandler(element, "click", updateHandler);
194.2246 -
194.2247 -        // IE 6 won't allow radio buttons to be selected unless they have a name
194.2248 -        if ((element.type == "radio") && !element.name)
194.2249 -            ko.bindingHandlers['uniqueName']['init'](element, function() { return true });
194.2250 -    },
194.2251 -    'update': function (element, valueAccessor) {
194.2252 -        var value = ko.utils.unwrapObservable(valueAccessor());
194.2253 -
194.2254 -        if (element.type == "checkbox") {
194.2255 -            if (value instanceof Array) {
194.2256 -                // When bound to an array, the checkbox being checked represents its value being present in that array
194.2257 -                element.checked = ko.utils.arrayIndexOf(value, element.value) >= 0;
194.2258 -            } else {
194.2259 -                // When bound to anything other value (not an array), the checkbox being checked represents the value being trueish
194.2260 -                element.checked = value;
194.2261 -            }
194.2262 -        } else if (element.type == "radio") {
194.2263 -            element.checked = (element.value == value);
194.2264 -        }
194.2265 -    }
194.2266 -};
194.2267 -var classesWrittenByBindingKey = '__ko__cssValue';
194.2268 -ko.bindingHandlers['css'] = {
194.2269 -    'update': function (element, valueAccessor) {
194.2270 -        var value = ko.utils.unwrapObservable(valueAccessor());
194.2271 -        if (typeof value == "object") {
194.2272 -            for (var className in value) {
194.2273 -                var shouldHaveClass = ko.utils.unwrapObservable(value[className]);
194.2274 -                ko.utils.toggleDomNodeCssClass(element, className, shouldHaveClass);
194.2275 -            }
194.2276 -        } else {
194.2277 -            value = String(value || ''); // Make sure we don't try to store or set a non-string value
194.2278 -            ko.utils.toggleDomNodeCssClass(element, element[classesWrittenByBindingKey], false);
194.2279 -            element[classesWrittenByBindingKey] = value;
194.2280 -            ko.utils.toggleDomNodeCssClass(element, value, true);
194.2281 -        }
194.2282 -    }
194.2283 -};
194.2284 -ko.bindingHandlers['enable'] = {
194.2285 -    'update': function (element, valueAccessor) {
194.2286 -        var value = ko.utils.unwrapObservable(valueAccessor());
194.2287 -        if (value && element.disabled)
194.2288 -            element.removeAttribute("disabled");
194.2289 -        else if ((!value) && (!element.disabled))
194.2290 -            element.disabled = true;
194.2291 -    }
194.2292 -};
194.2293 -
194.2294 -ko.bindingHandlers['disable'] = {
194.2295 -    'update': function (element, valueAccessor) {
194.2296 -        ko.bindingHandlers['enable']['update'](element, function() { return !ko.utils.unwrapObservable(valueAccessor()) });
194.2297 -    }
194.2298 -};
194.2299 -// For certain common events (currently just 'click'), allow a simplified data-binding syntax
194.2300 -// e.g. click:handler instead of the usual full-length event:{click:handler}
194.2301 -function makeEventHandlerShortcut(eventName) {
194.2302 -    ko.bindingHandlers[eventName] = {
194.2303 -        'init': function(element, valueAccessor, allBindingsAccessor, viewModel) {
194.2304 -            var newValueAccessor = function () {
194.2305 -                var result = {};
194.2306 -                result[eventName] = valueAccessor();
194.2307 -                return result;
194.2308 -            };
194.2309 -            return ko.bindingHandlers['event']['init'].call(this, element, newValueAccessor, allBindingsAccessor, viewModel);
194.2310 -        }
194.2311 -    }
194.2312 -}
194.2313 -
194.2314 -ko.bindingHandlers['event'] = {
194.2315 -    'init' : function (element, valueAccessor, allBindingsAccessor, viewModel) {
194.2316 -        var eventsToHandle = valueAccessor() || {};
194.2317 -        for(var eventNameOutsideClosure in eventsToHandle) {
194.2318 -            (function() {
194.2319 -                var eventName = eventNameOutsideClosure; // Separate variable to be captured by event handler closure
194.2320 -                if (typeof eventName == "string") {
194.2321 -                    ko.utils.registerEventHandler(element, eventName, function (event) {
194.2322 -                        var handlerReturnValue;
194.2323 -                        var handlerFunction = valueAccessor()[eventName];
194.2324 -                        if (!handlerFunction)
194.2325 -                            return;
194.2326 -                        var allBindings = allBindingsAccessor();
194.2327 -
194.2328 -                        try {
194.2329 -                            // Take all the event args, and prefix with the viewmodel
194.2330 -                            var argsForHandler = ko.utils.makeArray(arguments);
194.2331 -                            argsForHandler.unshift(viewModel);
194.2332 -                            handlerReturnValue = handlerFunction.apply(viewModel, argsForHandler);
194.2333 -                        } finally {
194.2334 -                            if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
194.2335 -                                if (event.preventDefault)
194.2336 -                                    event.preventDefault();
194.2337 -                                else
194.2338 -                                    event.returnValue = false;
194.2339 -                            }
194.2340 -                        }
194.2341 -
194.2342 -                        var bubble = allBindings[eventName + 'Bubble'] !== false;
194.2343 -                        if (!bubble) {
194.2344 -                            event.cancelBubble = true;
194.2345 -                            if (event.stopPropagation)
194.2346 -                                event.stopPropagation();
194.2347 -                        }
194.2348 -                    });
194.2349 -                }
194.2350 -            })();
194.2351 -        }
194.2352 -    }
194.2353 -};
194.2354 -// "foreach: someExpression" is equivalent to "template: { foreach: someExpression }"
194.2355 -// "foreach: { data: someExpression, afterAdd: myfn }" is equivalent to "template: { foreach: someExpression, afterAdd: myfn }"
194.2356 -ko.bindingHandlers['foreach'] = {
194.2357 -    makeTemplateValueAccessor: function(valueAccessor) {
194.2358 -        return function() {
194.2359 -            var modelValue = valueAccessor(),
194.2360 -                unwrappedValue = ko.utils.peekObservable(modelValue);    // Unwrap without setting a dependency here
194.2361 -
194.2362 -            // If unwrappedValue is the array, pass in the wrapped value on its own
194.2363 -            // The value will be unwrapped and tracked within the template binding
194.2364 -            // (See https://github.com/SteveSanderson/knockout/issues/523)
194.2365 -            if ((!unwrappedValue) || typeof unwrappedValue.length == "number")
194.2366 -                return { 'foreach': modelValue, 'templateEngine': ko.nativeTemplateEngine.instance };
194.2367 -
194.2368 -            // If unwrappedValue.data is the array, preserve all relevant options and unwrap again value so we get updates
194.2369 -            ko.utils.unwrapObservable(modelValue);
194.2370 -            return {
194.2371 -                'foreach': unwrappedValue['data'],
194.2372 -                'as': unwrappedValue['as'],
194.2373 -                'includeDestroyed': unwrappedValue['includeDestroyed'],
194.2374 -                'afterAdd': unwrappedValue['afterAdd'],
194.2375 -                'beforeRemove': unwrappedValue['beforeRemove'],
194.2376 -                'afterRender': unwrappedValue['afterRender'],
194.2377 -                'beforeMove': unwrappedValue['beforeMove'],
194.2378 -                'afterMove': unwrappedValue['afterMove'],
194.2379 -                'templateEngine': ko.nativeTemplateEngine.instance
194.2380 -            };
194.2381 -        };
194.2382 -    },
194.2383 -    'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
194.2384 -        return ko.bindingHandlers['template']['init'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor));
194.2385 -    },
194.2386 -    'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
194.2387 -        return ko.bindingHandlers['template']['update'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor), allBindingsAccessor, viewModel, bindingContext);
194.2388 -    }
194.2389 -};
194.2390 -ko.expressionRewriting.bindingRewriteValidators['foreach'] = false; // Can't rewrite control flow bindings
194.2391 -ko.virtualElements.allowedBindings['foreach'] = true;
194.2392 -var hasfocusUpdatingProperty = '__ko_hasfocusUpdating';
194.2393 -ko.bindingHandlers['hasfocus'] = {
194.2394 -    'init': function(element, valueAccessor, allBindingsAccessor) {
194.2395 -        var handleElementFocusChange = function(isFocused) {
194.2396 -            // Where possible, ignore which event was raised and determine focus state using activeElement,
194.2397 -            // as this avoids phantom focus/blur events raised when changing tabs in modern browsers.
194.2398 -            // However, not all KO-targeted browsers (Firefox 2) support activeElement. For those browsers,
194.2399 -            // prevent a loss of focus when changing tabs/windows by setting a flag that prevents hasfocus
194.2400 -            // from calling 'blur()' on the element when it loses focus.
194.2401 -            // Discussion at https://github.com/SteveSanderson/knockout/pull/352
194.2402 -            element[hasfocusUpdatingProperty] = true;
194.2403 -            var ownerDoc = element.ownerDocument;
194.2404 -            if ("activeElement" in ownerDoc) {
194.2405 -                isFocused = (ownerDoc.activeElement === element);
194.2406 -            }
194.2407 -            var modelValue = valueAccessor();
194.2408 -            ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'hasfocus', isFocused, true);
194.2409 -            element[hasfocusUpdatingProperty] = false;
194.2410 -        };
194.2411 -        var handleElementFocusIn = handleElementFocusChange.bind(null, true);
194.2412 -        var handleElementFocusOut = handleElementFocusChange.bind(null, false);
194.2413 -
194.2414 -        ko.utils.registerEventHandler(element, "focus", handleElementFocusIn);
194.2415 -        ko.utils.registerEventHandler(element, "focusin", handleElementFocusIn); // For IE
194.2416 -        ko.utils.registerEventHandler(element, "blur",  handleElementFocusOut);
194.2417 -        ko.utils.registerEventHandler(element, "focusout",  handleElementFocusOut); // For IE
194.2418 -    },
194.2419 -    'update': function(element, valueAccessor) {
194.2420 -        var value = ko.utils.unwrapObservable(valueAccessor());
194.2421 -        if (!element[hasfocusUpdatingProperty]) {
194.2422 -            value ? element.focus() : element.blur();
194.2423 -            ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, value ? "focusin" : "focusout"]); // For IE, which doesn't reliably fire "focus" or "blur" events synchronously
194.2424 -        }
194.2425 -    }
194.2426 -};
194.2427 -ko.bindingHandlers['html'] = {
194.2428 -    'init': function() {
194.2429 -        // Prevent binding on the dynamically-injected HTML (as developers are unlikely to expect that, and it has security implications)
194.2430 -        return { 'controlsDescendantBindings': true };
194.2431 -    },
194.2432 -    'update': function (element, valueAccessor) {
194.2433 -        // setHtml will unwrap the value if needed
194.2434 -        ko.utils.setHtml(element, valueAccessor());
194.2435 -    }
194.2436 -};
194.2437 -var withIfDomDataKey = '__ko_withIfBindingData';
194.2438 -// Makes a binding like with or if
194.2439 -function makeWithIfBinding(bindingKey, isWith, isNot, makeContextCallback) {
194.2440 -    ko.bindingHandlers[bindingKey] = {
194.2441 -        'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
194.2442 -            ko.utils.domData.set(element, withIfDomDataKey, {});
194.2443 -            return { 'controlsDescendantBindings': true };
194.2444 -        },
194.2445 -        'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
194.2446 -            var withIfData = ko.utils.domData.get(element, withIfDomDataKey),
194.2447 -                dataValue = ko.utils.unwrapObservable(valueAccessor()),
194.2448 -                shouldDisplay = !isNot !== !dataValue, // equivalent to isNot ? !dataValue : !!dataValue
194.2449 -                isFirstRender = !withIfData.savedNodes,
194.2450 -                needsRefresh = isFirstRender || isWith || (shouldDisplay !== withIfData.didDisplayOnLastUpdate);
194.2451 -
194.2452 -            if (needsRefresh) {
194.2453 -                if (isFirstRender) {
194.2454 -                    withIfData.savedNodes = ko.utils.cloneNodes(ko.virtualElements.childNodes(element), true /* shouldCleanNodes */);
194.2455 -                }
194.2456 -
194.2457 -                if (shouldDisplay) {
194.2458 -                    if (!isFirstRender) {
194.2459 -                        ko.virtualElements.setDomNodeChildren(element, ko.utils.cloneNodes(withIfData.savedNodes));
194.2460 -                    }
194.2461 -                    ko.applyBindingsToDescendants(makeContextCallback ? makeContextCallback(bindingContext, dataValue) : bindingContext, element);
194.2462 -                } else {
194.2463 -                    ko.virtualElements.emptyNode(element);
194.2464 -                }
194.2465 -
194.2466 -                withIfData.didDisplayOnLastUpdate = shouldDisplay;
194.2467 -            }
194.2468 -        }
194.2469 -    };
194.2470 -    ko.expressionRewriting.bindingRewriteValidators[bindingKey] = false; // Can't rewrite control flow bindings
194.2471 -    ko.virtualElements.allowedBindings[bindingKey] = true;
194.2472 -}
194.2473 -
194.2474 -// Construct the actual binding handlers
194.2475 -makeWithIfBinding('if');
194.2476 -makeWithIfBinding('ifnot', false /* isWith */, true /* isNot */);
194.2477 -makeWithIfBinding('with', true /* isWith */, false /* isNot */,
194.2478 -    function(bindingContext, dataValue) {
194.2479 -        return bindingContext['createChildContext'](dataValue);
194.2480 -    }
194.2481 -);
194.2482 -function ensureDropdownSelectionIsConsistentWithModelValue(element, modelValue, preferModelValue) {
194.2483 -    if (preferModelValue) {
194.2484 -        if (modelValue !== ko.selectExtensions.readValue(element))
194.2485 -            ko.selectExtensions.writeValue(element, modelValue);
194.2486 -    }
194.2487 -
194.2488 -    // No matter which direction we're syncing in, we want the end result to be equality between dropdown value and model value.
194.2489 -    // If they aren't equal, either we prefer the dropdown value, or the model value couldn't be represented, so either way,
194.2490 -    // change the model value to match the dropdown.
194.2491 -    if (modelValue !== ko.selectExtensions.readValue(element))
194.2492 -        ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, "change"]);
194.2493 -};
194.2494 -
194.2495 -ko.bindingHandlers['options'] = {
194.2496 -    'update': function (element, valueAccessor, allBindingsAccessor) {
194.2497 -        if (ko.utils.tagNameLower(element) !== "select")
194.2498 -            throw new Error("options binding applies only to SELECT elements");
194.2499 -
194.2500 -        var selectWasPreviouslyEmpty = element.length == 0;
194.2501 -        var previousSelectedValues = ko.utils.arrayMap(ko.utils.arrayFilter(element.childNodes, function (node) {
194.2502 -            return node.tagName && (ko.utils.tagNameLower(node) === "option") && node.selected;
194.2503 -        }), function (node) {
194.2504 -            return ko.selectExtensions.readValue(node) || node.innerText || node.textContent;
194.2505 -        });
194.2506 -        var previousScrollTop = element.scrollTop;
194.2507 -
194.2508 -        var value = ko.utils.unwrapObservable(valueAccessor());
194.2509 -        var selectedValue = element.value;
194.2510 -
194.2511 -        // Remove all existing <option>s.
194.2512 -        // Need to use .remove() rather than .removeChild() for <option>s otherwise IE behaves oddly (https://github.com/SteveSanderson/knockout/issues/134)
194.2513 -        while (element.length > 0) {
194.2514 -            ko.cleanNode(element.options[0]);
194.2515 -            element.remove(0);
194.2516 -        }
194.2517 -
194.2518 -        if (value) {
194.2519 -            var allBindings = allBindingsAccessor(),
194.2520 -                includeDestroyed = allBindings['optionsIncludeDestroyed'];
194.2521 -
194.2522 -            if (typeof value.length != "number")
194.2523 -                value = [value];
194.2524 -            if (allBindings['optionsCaption']) {
194.2525 -                var option = document.createElement("option");
194.2526 -                ko.utils.setHtml(option, allBindings['optionsCaption']);
194.2527 -                ko.selectExtensions.writeValue(option, undefined);
194.2528 -                element.appendChild(option);
194.2529 -            }
194.2530 -
194.2531 -            for (var i = 0, j = value.length; i < j; i++) {
194.2532 -                // Skip destroyed items
194.2533 -                var arrayEntry = value[i];
194.2534 -                if (arrayEntry && arrayEntry['_destroy'] && !includeDestroyed)
194.2535 -                    continue;
194.2536 -
194.2537 -                var option = document.createElement("option");
194.2538 -
194.2539 -                function applyToObject(object, predicate, defaultValue) {
194.2540 -                    var predicateType = typeof predicate;
194.2541 -                    if (predicateType == "function")    // Given a function; run it against the data value
194.2542 -                        return predicate(object);
194.2543 -                    else if (predicateType == "string") // Given a string; treat it as a property name on the data value
194.2544 -                        return object[predicate];
194.2545 -                    else                                // Given no optionsText arg; use the data value itself
194.2546 -                        return defaultValue;
194.2547 -                }
194.2548 -
194.2549 -                // Apply a value to the option element
194.2550 -                var optionValue = applyToObject(arrayEntry, allBindings['optionsValue'], arrayEntry);
194.2551 -                ko.selectExtensions.writeValue(option, ko.utils.unwrapObservable(optionValue));
194.2552 -
194.2553 -                // Apply some text to the option element
194.2554 -                var optionText = applyToObject(arrayEntry, allBindings['optionsText'], optionValue);
194.2555 -                ko.utils.setTextContent(option, optionText);
194.2556 -
194.2557 -                element.appendChild(option);
194.2558 -            }
194.2559 -
194.2560 -            // IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document.
194.2561 -            // That's why we first added them without selection. Now it's time to set the selection.
194.2562 -            var newOptions = element.getElementsByTagName("option");
194.2563 -            var countSelectionsRetained = 0;
194.2564 -            for (var i = 0, j = newOptions.length; i < j; i++) {
194.2565 -                if (ko.utils.arrayIndexOf(previousSelectedValues, ko.selectExtensions.readValue(newOptions[i])) >= 0) {
194.2566 -                    ko.utils.setOptionNodeSelectionState(newOptions[i], true);
194.2567 -                    countSelectionsRetained++;
194.2568 -                }
194.2569 -            }
194.2570 -
194.2571 -            element.scrollTop = previousScrollTop;
194.2572 -
194.2573 -            if (selectWasPreviouslyEmpty && ('value' in allBindings)) {
194.2574 -                // Ensure consistency between model value and selected option.
194.2575 -                // If the dropdown is being populated for the first time here (or was otherwise previously empty),
194.2576 -                // the dropdown selection state is meaningless, so we preserve the model value.
194.2577 -                ensureDropdownSelectionIsConsistentWithModelValue(element, ko.utils.peekObservable(allBindings['value']), /* preferModelValue */ true);
194.2578 -            }
194.2579 -
194.2580 -            // Workaround for IE9 bug
194.2581 -            ko.utils.ensureSelectElementIsRenderedCorrectly(element);
194.2582 -        }
194.2583 -    }
194.2584 -};
194.2585 -ko.bindingHandlers['options'].optionValueDomDataKey = '__ko.optionValueDomData__';
194.2586 -ko.bindingHandlers['selectedOptions'] = {
194.2587 -    'init': function (element, valueAccessor, allBindingsAccessor) {
194.2588 -        ko.utils.registerEventHandler(element, "change", function () {
194.2589 -            var value = valueAccessor(), valueToWrite = [];
194.2590 -            ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
194.2591 -                if (node.selected)
194.2592 -                    valueToWrite.push(ko.selectExtensions.readValue(node));
194.2593 -            });
194.2594 -            ko.expressionRewriting.writeValueToProperty(value, allBindingsAccessor, 'value', valueToWrite);
194.2595 -        });
194.2596 -    },
194.2597 -    'update': function (element, valueAccessor) {
194.2598 -        if (ko.utils.tagNameLower(element) != "select")
194.2599 -            throw new Error("values binding applies only to SELECT elements");
194.2600 -
194.2601 -        var newValue = ko.utils.unwrapObservable(valueAccessor());
194.2602 -        if (newValue && typeof newValue.length == "number") {
194.2603 -            ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
194.2604 -                var isSelected = ko.utils.arrayIndexOf(newValue, ko.selectExtensions.readValue(node)) >= 0;
194.2605 -                ko.utils.setOptionNodeSelectionState(node, isSelected);
194.2606 -            });
194.2607 -        }
194.2608 -    }
194.2609 -};
194.2610 -ko.bindingHandlers['style'] = {
194.2611 -    'update': function (element, valueAccessor) {
194.2612 -        var value = ko.utils.unwrapObservable(valueAccessor() || {});
194.2613 -        for (var styleName in value) {
194.2614 -            if (typeof styleName == "string") {
194.2615 -                var styleValue = ko.utils.unwrapObservable(value[styleName]);
194.2616 -                element.style[styleName] = styleValue || ""; // Empty string removes the value, whereas null/undefined have no effect
194.2617 -            }
194.2618 -        }
194.2619 -    }
194.2620 -};
194.2621 -ko.bindingHandlers['submit'] = {
194.2622 -    'init': function (element, valueAccessor, allBindingsAccessor, viewModel) {
194.2623 -        if (typeof valueAccessor() != "function")
194.2624 -            throw new Error("The value for a submit binding must be a function");
194.2625 -        ko.utils.registerEventHandler(element, "submit", function (event) {
194.2626 -            var handlerReturnValue;
194.2627 -            var value = valueAccessor();
194.2628 -            try { handlerReturnValue = value.call(viewModel, element); }
194.2629 -            finally {
194.2630 -                if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
194.2631 -                    if (event.preventDefault)
194.2632 -                        event.preventDefault();
194.2633 -                    else
194.2634 -                        event.returnValue = false;
194.2635 -                }
194.2636 -            }
194.2637 -        });
194.2638 -    }
194.2639 -};
194.2640 -ko.bindingHandlers['text'] = {
194.2641 -    'update': function (element, valueAccessor) {
194.2642 -        ko.utils.setTextContent(element, valueAccessor());
194.2643 -    }
194.2644 -};
194.2645 -ko.virtualElements.allowedBindings['text'] = true;
194.2646 -ko.bindingHandlers['uniqueName'] = {
194.2647 -    'init': function (element, valueAccessor) {
194.2648 -        if (valueAccessor()) {
194.2649 -            var name = "ko_unique_" + (++ko.bindingHandlers['uniqueName'].currentIndex);
194.2650 -            ko.utils.setElementName(element, name);
194.2651 -        }
194.2652 -    }
194.2653 -};
194.2654 -ko.bindingHandlers['uniqueName'].currentIndex = 0;
194.2655 -ko.bindingHandlers['value'] = {
194.2656 -    'init': function (element, valueAccessor, allBindingsAccessor) {
194.2657 -        // Always catch "change" event; possibly other events too if asked
194.2658 -        var eventsToCatch = ["change"];
194.2659 -        var requestedEventsToCatch = allBindingsAccessor()["valueUpdate"];
194.2660 -        var propertyChangedFired = false;
194.2661 -        if (requestedEventsToCatch) {
194.2662 -            if (typeof requestedEventsToCatch == "string") // Allow both individual event names, and arrays of event names
194.2663 -                requestedEventsToCatch = [requestedEventsToCatch];
194.2664 -            ko.utils.arrayPushAll(eventsToCatch, requestedEventsToCatch);
194.2665 -            eventsToCatch = ko.utils.arrayGetDistinctValues(eventsToCatch);
194.2666 -        }
194.2667 -
194.2668 -        var valueUpdateHandler = function() {
194.2669 -            propertyChangedFired = false;
194.2670 -            var modelValue = valueAccessor();
194.2671 -            var elementValue = ko.selectExtensions.readValue(element);
194.2672 -            ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'value', elementValue);
194.2673 -        }
194.2674 -
194.2675 -        // Workaround for https://github.com/SteveSanderson/knockout/issues/122
194.2676 -        // IE doesn't fire "change" events on textboxes if the user selects a value from its autocomplete list
194.2677 -        var ieAutoCompleteHackNeeded = ko.utils.ieVersion && element.tagName.toLowerCase() == "input" && element.type == "text"
194.2678 -                                       && element.autocomplete != "off" && (!element.form || element.form.autocomplete != "off");
194.2679 -        if (ieAutoCompleteHackNeeded && ko.utils.arrayIndexOf(eventsToCatch, "propertychange") == -1) {
194.2680 -            ko.utils.registerEventHandler(element, "propertychange", function () { propertyChangedFired = true });
194.2681 -            ko.utils.registerEventHandler(element, "blur", function() {
194.2682 -                if (propertyChangedFired) {
194.2683 -                    valueUpdateHandler();
194.2684 -                }
194.2685 -            });
194.2686 -        }
194.2687 -
194.2688 -        ko.utils.arrayForEach(eventsToCatch, function(eventName) {
194.2689 -            // The syntax "after<eventname>" means "run the handler asynchronously after the event"
194.2690 -            // This is useful, for example, to catch "keydown" events after the browser has updated the control
194.2691 -            // (otherwise, ko.selectExtensions.readValue(this) will receive the control's value *before* the key event)
194.2692 -            var handler = valueUpdateHandler;
194.2693 -            if (ko.utils.stringStartsWith(eventName, "after")) {
194.2694 -                handler = function() { setTimeout(valueUpdateHandler, 0) };
194.2695 -                eventName = eventName.substring("after".length);
194.2696 -            }
194.2697 -            ko.utils.registerEventHandler(element, eventName, handler);
194.2698 -        });
194.2699 -    },
194.2700 -    'update': function (element, valueAccessor) {
194.2701 -        var valueIsSelectOption = ko.utils.tagNameLower(element) === "select";
194.2702 -        var newValue = ko.utils.unwrapObservable(valueAccessor());
194.2703 -        var elementValue = ko.selectExtensions.readValue(element);
194.2704 -        var valueHasChanged = (newValue != elementValue);
194.2705 -
194.2706 -        // JavaScript's 0 == "" behavious is unfortunate here as it prevents writing 0 to an empty text box (loose equality suggests the values are the same).
194.2707 -        // We don't want to do a strict equality comparison as that is more confusing for developers in certain cases, so we specifically special case 0 != "" here.
194.2708 -        if ((newValue === 0) && (elementValue !== 0) && (elementValue !== "0"))
194.2709 -            valueHasChanged = true;
194.2710 -
194.2711 -        if (valueHasChanged) {
194.2712 -            var applyValueAction = function () { ko.selectExtensions.writeValue(element, newValue); };
194.2713 -            applyValueAction();
194.2714 -
194.2715 -            // Workaround for IE6 bug: It won't reliably apply values to SELECT nodes during the same execution thread
194.2716 -            // right after you've changed the set of OPTION nodes on it. So for that node type, we'll schedule a second thread
194.2717 -            // to apply the value as well.
194.2718 -            var alsoApplyAsynchronously = valueIsSelectOption;
194.2719 -            if (alsoApplyAsynchronously)
194.2720 -                setTimeout(applyValueAction, 0);
194.2721 -        }
194.2722 -
194.2723 -        // If you try to set a model value that can't be represented in an already-populated dropdown, reject that change,
194.2724 -        // because you're not allowed to have a model value that disagrees with a visible UI selection.
194.2725 -        if (valueIsSelectOption && (element.length > 0))
194.2726 -            ensureDropdownSelectionIsConsistentWithModelValue(element, newValue, /* preferModelValue */ false);
194.2727 -    }
194.2728 -};
194.2729 -ko.bindingHandlers['visible'] = {
194.2730 -    'update': function (element, valueAccessor) {
194.2731 -        var value = ko.utils.unwrapObservable(valueAccessor());
194.2732 -        var isCurrentlyVisible = !(element.style.display == "none");
194.2733 -        if (value && !isCurrentlyVisible)
194.2734 -            element.style.display = "";
194.2735 -        else if ((!value) && isCurrentlyVisible)
194.2736 -            element.style.display = "none";
194.2737 -    }
194.2738 -};
194.2739 -// 'click' is just a shorthand for the usual full-length event:{click:handler}
194.2740 -makeEventHandlerShortcut('click');
194.2741 -// If you want to make a custom template engine,
194.2742 -//
194.2743 -// [1] Inherit from this class (like ko.nativeTemplateEngine does)
194.2744 -// [2] Override 'renderTemplateSource', supplying a function with this signature:
194.2745 -//
194.2746 -//        function (templateSource, bindingContext, options) {
194.2747 -//            // - templateSource.text() is the text of the template you should render
194.2748 -//            // - bindingContext.$data is the data you should pass into the template
194.2749 -//            //   - you might also want to make bindingContext.$parent, bindingContext.$parents,
194.2750 -//            //     and bindingContext.$root available in the template too
194.2751 -//            // - options gives you access to any other properties set on "data-bind: { template: options }"
194.2752 -//            //
194.2753 -//            // Return value: an array of DOM nodes
194.2754 -//        }
194.2755 -//
194.2756 -// [3] Override 'createJavaScriptEvaluatorBlock', supplying a function with this signature:
194.2757 -//
194.2758 -//        function (script) {
194.2759 -//            // Return value: Whatever syntax means "Evaluate the JavaScript statement 'script' and output the result"
194.2760 -//            //               For example, the jquery.tmpl template engine converts 'someScript' to '${ someScript }'
194.2761 -//        }
194.2762 -//
194.2763 -//     This is only necessary if you want to allow data-bind attributes to reference arbitrary template variables.
194.2764 -//     If you don't want to allow that, you can set the property 'allowTemplateRewriting' to false (like ko.nativeTemplateEngine does)
194.2765 -//     and then you don't need to override 'createJavaScriptEvaluatorBlock'.
194.2766 -
194.2767 -ko.templateEngine = function () { };
194.2768 -
194.2769 -ko.templateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
194.2770 -    throw new Error("Override renderTemplateSource");
194.2771 -};
194.2772 -
194.2773 -ko.templateEngine.prototype['createJavaScriptEvaluatorBlock'] = function (script) {
194.2774 -    throw new Error("Override createJavaScriptEvaluatorBlock");
194.2775 -};
194.2776 -
194.2777 -ko.templateEngine.prototype['makeTemplateSource'] = function(template, templateDocument) {
194.2778 -    // Named template
194.2779 -    if (typeof template == "string") {
194.2780 -        templateDocument = templateDocument || document;
194.2781 -        var elem = templateDocument.getElementById(template);
194.2782 -        if (!elem)
194.2783 -            throw new Error("Cannot find template with ID " + template);
194.2784 -        return new ko.templateSources.domElement(elem);
194.2785 -    } else if ((template.nodeType == 1) || (template.nodeType == 8)) {
194.2786 -        // Anonymous template
194.2787 -        return new ko.templateSources.anonymousTemplate(template);
194.2788 -    } else
194.2789 -        throw new Error("Unknown template type: " + template);
194.2790 -};
194.2791 -
194.2792 -ko.templateEngine.prototype['renderTemplate'] = function (template, bindingContext, options, templateDocument) {
194.2793 -    var templateSource = this['makeTemplateSource'](template, templateDocument);
194.2794 -    return this['renderTemplateSource'](templateSource, bindingContext, options);
194.2795 -};
194.2796 -
194.2797 -ko.templateEngine.prototype['isTemplateRewritten'] = function (template, templateDocument) {
194.2798 -    // Skip rewriting if requested
194.2799 -    if (this['allowTemplateRewriting'] === false)
194.2800 -        return true;
194.2801 -    return this['makeTemplateSource'](template, templateDocument)['data']("isRewritten");
194.2802 -};
194.2803 -
194.2804 -ko.templateEngine.prototype['rewriteTemplate'] = function (template, rewriterCallback, templateDocument) {
194.2805 -    var templateSource = this['makeTemplateSource'](template, templateDocument);
194.2806 -    var rewritten = rewriterCallback(templateSource['text']());
194.2807 -    templateSource['text'](rewritten);
194.2808 -    templateSource['data']("isRewritten", true);
194.2809 -};
194.2810 -
194.2811 -ko.exportSymbol('templateEngine', ko.templateEngine);
194.2812 -
194.2813 -ko.templateRewriting = (function () {
194.2814 -    var memoizeDataBindingAttributeSyntaxRegex = /(<[a-z]+\d*(\s+(?!data-bind=)[a-z0-9\-]+(=(\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind=(["'])([\s\S]*?)\5/gi;
194.2815 -    var memoizeVirtualContainerBindingSyntaxRegex = /<!--\s*ko\b\s*([\s\S]*?)\s*-->/g;
194.2816 -
194.2817 -    function validateDataBindValuesForRewriting(keyValueArray) {
194.2818 -        var allValidators = ko.expressionRewriting.bindingRewriteValidators;
194.2819 -        for (var i = 0; i < keyValueArray.length; i++) {
194.2820 -            var key = keyValueArray[i]['key'];
194.2821 -            if (allValidators.hasOwnProperty(key)) {
194.2822 -                var validator = allValidators[key];
194.2823 -
194.2824 -                if (typeof validator === "function") {
194.2825 -                    var possibleErrorMessage = validator(keyValueArray[i]['value']);
194.2826 -                    if (possibleErrorMessage)
194.2827 -                        throw new Error(possibleErrorMessage);
194.2828 -                } else if (!validator) {
194.2829 -                    throw new Error("This template engine does not support the '" + key + "' binding within its templates");
194.2830 -                }
194.2831 -            }
194.2832 -        }
194.2833 -    }
194.2834 -
194.2835 -    function constructMemoizedTagReplacement(dataBindAttributeValue, tagToRetain, templateEngine) {
194.2836 -        var dataBindKeyValueArray = ko.expressionRewriting.parseObjectLiteral(dataBindAttributeValue);
194.2837 -        validateDataBindValuesForRewriting(dataBindKeyValueArray);
194.2838 -        var rewrittenDataBindAttributeValue = ko.expressionRewriting.preProcessBindings(dataBindKeyValueArray);
194.2839 -
194.2840 -        // For no obvious reason, Opera fails to evaluate rewrittenDataBindAttributeValue unless it's wrapped in an additional
194.2841 -        // anonymous function, even though Opera's built-in debugger can evaluate it anyway. No other browser requires this
194.2842 -        // extra indirection.
194.2843 -        var applyBindingsToNextSiblingScript =
194.2844 -            "ko.__tr_ambtns(function($context,$element){return(function(){return{ " + rewrittenDataBindAttributeValue + " } })()})";
194.2845 -        return templateEngine['createJavaScriptEvaluatorBlock'](applyBindingsToNextSiblingScript) + tagToRetain;
194.2846 -    }
194.2847 -
194.2848 -    return {
194.2849 -        ensureTemplateIsRewritten: function (template, templateEngine, templateDocument) {
194.2850 -            if (!templateEngine['isTemplateRewritten'](template, templateDocument))
194.2851 -                templateEngine['rewriteTemplate'](template, function (htmlString) {
194.2852 -                    return ko.templateRewriting.memoizeBindingAttributeSyntax(htmlString, templateEngine);
194.2853 -                }, templateDocument);
194.2854 -        },
194.2855 -
194.2856 -        memoizeBindingAttributeSyntax: function (htmlString, templateEngine) {
194.2857 -            return htmlString.replace(memoizeDataBindingAttributeSyntaxRegex, function () {
194.2858 -                return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[6], /* tagToRetain: */ arguments[1], templateEngine);
194.2859 -            }).replace(memoizeVirtualContainerBindingSyntaxRegex, function() {
194.2860 -                return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[1], /* tagToRetain: */ "<!-- ko -->", templateEngine);
194.2861 -            });
194.2862 -        },
194.2863 -
194.2864 -        applyMemoizedBindingsToNextSibling: function (bindings) {
194.2865 -            return ko.memoization.memoize(function (domNode, bindingContext) {
194.2866 -                if (domNode.nextSibling)
194.2867 -                    ko.applyBindingsToNode(domNode.nextSibling, bindings, bindingContext);
194.2868 -            });
194.2869 -        }
194.2870 -    }
194.2871 -})();
194.2872 -
194.2873 -
194.2874 -// Exported only because it has to be referenced by string lookup from within rewritten template
194.2875 -ko.exportSymbol('__tr_ambtns', ko.templateRewriting.applyMemoizedBindingsToNextSibling);
194.2876 -(function() {
194.2877 -    // A template source represents a read/write way of accessing a template. This is to eliminate the need for template loading/saving
194.2878 -    // logic to be duplicated in every template engine (and means they can all work with anonymous templates, etc.)
194.2879 -    //
194.2880 -    // Two are provided by default:
194.2881 -    //  1. ko.templateSources.domElement       - reads/writes the text content of an arbitrary DOM element
194.2882 -    //  2. ko.templateSources.anonymousElement - uses ko.utils.domData to read/write text *associated* with the DOM element, but
194.2883 -    //                                           without reading/writing the actual element text content, since it will be overwritten
194.2884 -    //                                           with the rendered template output.
194.2885 -    // You can implement your own template source if you want to fetch/store templates somewhere other than in DOM elements.
194.2886 -    // Template sources need to have the following functions:
194.2887 -    //   text() 			- returns the template text from your storage location
194.2888 -    //   text(value)		- writes the supplied template text to your storage location
194.2889 -    //   data(key)			- reads values stored using data(key, value) - see below
194.2890 -    //   data(key, value)	- associates "value" with this template and the key "key". Is used to store information like "isRewritten".
194.2891 -    //
194.2892 -    // Optionally, template sources can also have the following functions:
194.2893 -    //   nodes()            - returns a DOM element containing the nodes of this template, where available
194.2894 -    //   nodes(value)       - writes the given DOM element to your storage location
194.2895 -    // If a DOM element is available for a given template source, template engines are encouraged to use it in preference over text()
194.2896 -    // for improved speed. However, all templateSources must supply text() even if they don't supply nodes().
194.2897 -    //
194.2898 -    // Once you've implemented a templateSource, make your template engine use it by subclassing whatever template engine you were
194.2899 -    // using and overriding "makeTemplateSource" to return an instance of your custom template source.
194.2900 -
194.2901 -    ko.templateSources = {};
194.2902 -
194.2903 -    // ---- ko.templateSources.domElement -----
194.2904 -
194.2905 -    ko.templateSources.domElement = function(element) {
194.2906 -        this.domElement = element;
194.2907 -    }
194.2908 -
194.2909 -    ko.templateSources.domElement.prototype['text'] = function(/* valueToWrite */) {
194.2910 -        var tagNameLower = ko.utils.tagNameLower(this.domElement),
194.2911 -            elemContentsProperty = tagNameLower === "script" ? "text"
194.2912 -                                 : tagNameLower === "textarea" ? "value"
194.2913 -                                 : "innerHTML";
194.2914 -
194.2915 -        if (arguments.length == 0) {
194.2916 -            return this.domElement[elemContentsProperty];
194.2917 -        } else {
194.2918 -            var valueToWrite = arguments[0];
194.2919 -            if (elemContentsProperty === "innerHTML")
194.2920 -                ko.utils.setHtml(this.domElement, valueToWrite);
194.2921 -            else
194.2922 -                this.domElement[elemContentsProperty] = valueToWrite;
194.2923 -        }
194.2924 -    };
194.2925 -
194.2926 -    ko.templateSources.domElement.prototype['data'] = function(key /*, valueToWrite */) {
194.2927 -        if (arguments.length === 1) {
194.2928 -            return ko.utils.domData.get(this.domElement, "templateSourceData_" + key);
194.2929 -        } else {
194.2930 -            ko.utils.domData.set(this.domElement, "templateSourceData_" + key, arguments[1]);
194.2931 -        }
194.2932 -    };
194.2933 -
194.2934 -    // ---- ko.templateSources.anonymousTemplate -----
194.2935 -    // Anonymous templates are normally saved/retrieved as DOM nodes through "nodes".
194.2936 -    // For compatibility, you can also read "text"; it will be serialized from the nodes on demand.
194.2937 -    // Writing to "text" is still supported, but then the template data will not be available as DOM nodes.
194.2938 -
194.2939 -    var anonymousTemplatesDomDataKey = "__ko_anon_template__";
194.2940 -    ko.templateSources.anonymousTemplate = function(element) {
194.2941 -        this.domElement = element;
194.2942 -    }
194.2943 -    ko.templateSources.anonymousTemplate.prototype = new ko.templateSources.domElement();
194.2944 -    ko.templateSources.anonymousTemplate.prototype['text'] = function(/* valueToWrite */) {
194.2945 -        if (arguments.length == 0) {
194.2946 -            var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
194.2947 -            if (templateData.textData === undefined && templateData.containerData)
194.2948 -                templateData.textData = templateData.containerData.innerHTML;
194.2949 -            return templateData.textData;
194.2950 -        } else {
194.2951 -            var valueToWrite = arguments[0];
194.2952 -            ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {textData: valueToWrite});
194.2953 -        }
194.2954 -    };
194.2955 -    ko.templateSources.domElement.prototype['nodes'] = function(/* valueToWrite */) {
194.2956 -        if (arguments.length == 0) {
194.2957 -            var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
194.2958 -            return templateData.containerData;
194.2959 -        } else {
194.2960 -            var valueToWrite = arguments[0];
194.2961 -            ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {containerData: valueToWrite});
194.2962 -        }
194.2963 -    };
194.2964 -
194.2965 -    ko.exportSymbol('templateSources', ko.templateSources);
194.2966 -    ko.exportSymbol('templateSources.domElement', ko.templateSources.domElement);
194.2967 -    ko.exportSymbol('templateSources.anonymousTemplate', ko.templateSources.anonymousTemplate);
194.2968 -})();
194.2969 -(function () {
194.2970 -    var _templateEngine;
194.2971 -    ko.setTemplateEngine = function (templateEngine) {
194.2972 -        if ((templateEngine != undefined) && !(templateEngine instanceof ko.templateEngine))
194.2973 -            throw new Error("templateEngine must inherit from ko.templateEngine");
194.2974 -        _templateEngine = templateEngine;
194.2975 -    }
194.2976 -
194.2977 -    function invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, action) {
194.2978 -        var node, nextInQueue = firstNode, firstOutOfRangeNode = ko.virtualElements.nextSibling(lastNode);
194.2979 -        while (nextInQueue && ((node = nextInQueue) !== firstOutOfRangeNode)) {
194.2980 -            nextInQueue = ko.virtualElements.nextSibling(node);
194.2981 -            if (node.nodeType === 1 || node.nodeType === 8)
194.2982 -                action(node);
194.2983 -        }
194.2984 -    }
194.2985 -
194.2986 -    function activateBindingsOnContinuousNodeArray(continuousNodeArray, bindingContext) {
194.2987 -        // To be used on any nodes that have been rendered by a template and have been inserted into some parent element
194.2988 -        // Walks through continuousNodeArray (which *must* be continuous, i.e., an uninterrupted sequence of sibling nodes, because
194.2989 -        // the algorithm for walking them relies on this), and for each top-level item in the virtual-element sense,
194.2990 -        // (1) Does a regular "applyBindings" to associate bindingContext with this node and to activate any non-memoized bindings
194.2991 -        // (2) Unmemoizes any memos in the DOM subtree (e.g., to activate bindings that had been memoized during template rewriting)
194.2992 -
194.2993 -        if (continuousNodeArray.length) {
194.2994 -            var firstNode = continuousNodeArray[0], lastNode = continuousNodeArray[continuousNodeArray.length - 1];
194.2995 -
194.2996 -            // Need to applyBindings *before* unmemoziation, because unmemoization might introduce extra nodes (that we don't want to re-bind)
194.2997 -            // whereas a regular applyBindings won't introduce new memoized nodes
194.2998 -            invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
194.2999 -                ko.applyBindings(bindingContext, node);
194.3000 -            });
194.3001 -            invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
194.3002 -                ko.memoization.unmemoizeDomNodeAndDescendants(node, [bindingContext]);
194.3003 -            });
194.3004 -        }
194.3005 -    }
194.3006 -
194.3007 -    function getFirstNodeFromPossibleArray(nodeOrNodeArray) {
194.3008 -        return nodeOrNodeArray.nodeType ? nodeOrNodeArray
194.3009 -                                        : nodeOrNodeArray.length > 0 ? nodeOrNodeArray[0]
194.3010 -                                        : null;
194.3011 -    }
194.3012 -
194.3013 -    function executeTemplate(targetNodeOrNodeArray, renderMode, template, bindingContext, options) {
194.3014 -        options = options || {};
194.3015 -        var firstTargetNode = targetNodeOrNodeArray && getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
194.3016 -        var templateDocument = firstTargetNode && firstTargetNode.ownerDocument;
194.3017 -        var templateEngineToUse = (options['templateEngine'] || _templateEngine);
194.3018 -        ko.templateRewriting.ensureTemplateIsRewritten(template, templateEngineToUse, templateDocument);
194.3019 -        var renderedNodesArray = templateEngineToUse['renderTemplate'](template, bindingContext, options, templateDocument);
194.3020 -
194.3021 -        // Loosely check result is an array of DOM nodes
194.3022 -        if ((typeof renderedNodesArray.length != "number") || (renderedNodesArray.length > 0 && typeof renderedNodesArray[0].nodeType != "number"))
194.3023 -            throw new Error("Template engine must return an array of DOM nodes");
194.3024 -
194.3025 -        var haveAddedNodesToParent = false;
194.3026 -        switch (renderMode) {
194.3027 -            case "replaceChildren":
194.3028 -                ko.virtualElements.setDomNodeChildren(targetNodeOrNodeArray, renderedNodesArray);
194.3029 -                haveAddedNodesToParent = true;
194.3030 -                break;
194.3031 -            case "replaceNode":
194.3032 -                ko.utils.replaceDomNodes(targetNodeOrNodeArray, renderedNodesArray);
194.3033 -                haveAddedNodesToParent = true;
194.3034 -                break;
194.3035 -            case "ignoreTargetNode": break;
194.3036 -            default:
194.3037 -                throw new Error("Unknown renderMode: " + renderMode);
194.3038 -        }
194.3039 -
194.3040 -        if (haveAddedNodesToParent) {
194.3041 -            activateBindingsOnContinuousNodeArray(renderedNodesArray, bindingContext);
194.3042 -            if (options['afterRender'])
194.3043 -                ko.dependencyDetection.ignore(options['afterRender'], null, [renderedNodesArray, bindingContext['$data']]);
194.3044 -        }
194.3045 -
194.3046 -        return renderedNodesArray;
194.3047 -    }
194.3048 -
194.3049 -    ko.renderTemplate = function (template, dataOrBindingContext, options, targetNodeOrNodeArray, renderMode) {
194.3050 -        options = options || {};
194.3051 -        if ((options['templateEngine'] || _templateEngine) == undefined)
194.3052 -            throw new Error("Set a template engine before calling renderTemplate");
194.3053 -        renderMode = renderMode || "replaceChildren";
194.3054 -
194.3055 -        if (targetNodeOrNodeArray) {
194.3056 -            var firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
194.3057 -
194.3058 -            var whenToDispose = function () { return (!firstTargetNode) || !ko.utils.domNodeIsAttachedToDocument(firstTargetNode); }; // Passive disposal (on next evaluation)
194.3059 -            var activelyDisposeWhenNodeIsRemoved = (firstTargetNode && renderMode == "replaceNode") ? firstTargetNode.parentNode : firstTargetNode;
194.3060 -
194.3061 -            return ko.dependentObservable( // So the DOM is automatically updated when any dependency changes
194.3062 -                function () {
194.3063 -                    // Ensure we've got a proper binding context to work with
194.3064 -                    var bindingContext = (dataOrBindingContext && (dataOrBindingContext instanceof ko.bindingContext))
194.3065 -                        ? dataOrBindingContext
194.3066 -                        : new ko.bindingContext(ko.utils.unwrapObservable(dataOrBindingContext));
194.3067 -
194.3068 -                    // Support selecting template as a function of the data being rendered
194.3069 -                    var templateName = typeof(template) == 'function' ? template(bindingContext['$data'], bindingContext) : template;
194.3070 -
194.3071 -                    var renderedNodesArray = executeTemplate(targetNodeOrNodeArray, renderMode, templateName, bindingContext, options);
194.3072 -                    if (renderMode == "replaceNode") {
194.3073 -                        targetNodeOrNodeArray = renderedNodesArray;
194.3074 -                        firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
194.3075 -                    }
194.3076 -                },
194.3077 -                null,
194.3078 -                { disposeWhen: whenToDispose, disposeWhenNodeIsRemoved: activelyDisposeWhenNodeIsRemoved }
194.3079 -            );
194.3080 -        } else {
194.3081 -            // We don't yet have a DOM node to evaluate, so use a memo and render the template later when there is a DOM node
194.3082 -            return ko.memoization.memoize(function (domNode) {
194.3083 -                ko.renderTemplate(template, dataOrBindingContext, options, domNode, "replaceNode");
194.3084 -            });
194.3085 -        }
194.3086 -    };
194.3087 -
194.3088 -    ko.renderTemplateForEach = function (template, arrayOrObservableArray, options, targetNode, parentBindingContext) {
194.3089 -        // Since setDomNodeChildrenFromArrayMapping always calls executeTemplateForArrayItem and then
194.3090 -        // activateBindingsCallback for added items, we can store the binding context in the former to use in the latter.
194.3091 -        var arrayItemContext;
194.3092 -
194.3093 -        // This will be called by setDomNodeChildrenFromArrayMapping to get the nodes to add to targetNode
194.3094 -        var executeTemplateForArrayItem = function (arrayValue, index) {
194.3095 -            // Support selecting template as a function of the data being rendered
194.3096 -            arrayItemContext = parentBindingContext['createChildContext'](ko.utils.unwrapObservable(arrayValue), options['as']);
194.3097 -            arrayItemContext['$index'] = index;
194.3098 -            var templateName = typeof(template) == 'function' ? template(arrayValue, arrayItemContext) : template;
194.3099 -            return executeTemplate(null, "ignoreTargetNode", templateName, arrayItemContext, options);
194.3100 -        }
194.3101 -
194.3102 -        // This will be called whenever setDomNodeChildrenFromArrayMapping has added nodes to targetNode
194.3103 -        var activateBindingsCallback = function(arrayValue, addedNodesArray, index) {
194.3104 -            activateBindingsOnContinuousNodeArray(addedNodesArray, arrayItemContext);
194.3105 -            if (options['afterRender'])
194.3106 -                options['afterRender'](addedNodesArray, arrayValue);
194.3107 -        };
194.3108 -
194.3109 -        return ko.dependentObservable(function () {
194.3110 -            var unwrappedArray = ko.utils.unwrapObservable(arrayOrObservableArray) || [];
194.3111 -            if (typeof unwrappedArray.length == "undefined") // Coerce single value into array
194.3112 -                unwrappedArray = [unwrappedArray];
194.3113 -
194.3114 -            // Filter out any entries marked as destroyed
194.3115 -            var filteredArray = ko.utils.arrayFilter(unwrappedArray, function(item) {
194.3116 -                return options['includeDestroyed'] || item === undefined || item === null || !ko.utils.unwrapObservable(item['_destroy']);
194.3117 -            });
194.3118 -
194.3119 -            // Call setDomNodeChildrenFromArrayMapping, ignoring any observables unwrapped within (most likely from a callback function).
194.3120 -            // If the array items are observables, though, they will be unwrapped in executeTemplateForArrayItem and managed within setDomNodeChildrenFromArrayMapping.
194.3121 -            ko.dependencyDetection.ignore(ko.utils.setDomNodeChildrenFromArrayMapping, null, [targetNode, filteredArray, executeTemplateForArrayItem, options, activateBindingsCallback]);
194.3122 -
194.3123 -        }, null, { disposeWhenNodeIsRemoved: targetNode });
194.3124 -    };
194.3125 -
194.3126 -    var templateComputedDomDataKey = '__ko__templateComputedDomDataKey__';
194.3127 -    function disposeOldComputedAndStoreNewOne(element, newComputed) {
194.3128 -        var oldComputed = ko.utils.domData.get(element, templateComputedDomDataKey);
194.3129 -        if (oldComputed && (typeof(oldComputed.dispose) == 'function'))
194.3130 -            oldComputed.dispose();
194.3131 -        ko.utils.domData.set(element, templateComputedDomDataKey, (newComputed && newComputed.isActive()) ? newComputed : undefined);
194.3132 -    }
194.3133 -
194.3134 -    ko.bindingHandlers['template'] = {
194.3135 -        'init': function(element, valueAccessor) {
194.3136 -            // Support anonymous templates
194.3137 -            var bindingValue = ko.utils.unwrapObservable(valueAccessor());
194.3138 -            if ((typeof bindingValue != "string") && (!bindingValue['name']) && (element.nodeType == 1 || element.nodeType == 8)) {
194.3139 -                // It's an anonymous template - store the element contents, then clear the element
194.3140 -                var templateNodes = element.nodeType == 1 ? element.childNodes : ko.virtualElements.childNodes(element),
194.3141 -                    container = ko.utils.moveCleanedNodesToContainerElement(templateNodes); // This also removes the nodes from their current parent
194.3142 -                new ko.templateSources.anonymousTemplate(element)['nodes'](container);
194.3143 -            }
194.3144 -            return { 'controlsDescendantBindings': true };
194.3145 -        },
194.3146 -        'update': function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
194.3147 -            var templateName = ko.utils.unwrapObservable(valueAccessor()),
194.3148 -                options = {},
194.3149 -                shouldDisplay = true,
194.3150 -                dataValue,
194.3151 -                templateComputed = null;
194.3152 -
194.3153 -            if (typeof templateName != "string") {
194.3154 -                options = templateName;
194.3155 -                templateName = options['name'];
194.3156 -
194.3157 -                // Support "if"/"ifnot" conditions
194.3158 -                if ('if' in options)
194.3159 -                    shouldDisplay = ko.utils.unwrapObservable(options['if']);
194.3160 -                if (shouldDisplay && 'ifnot' in options)
194.3161 -                    shouldDisplay = !ko.utils.unwrapObservable(options['ifnot']);
194.3162 -
194.3163 -                dataValue = ko.utils.unwrapObservable(options['data']);
194.3164 -            }
194.3165 -
194.3166 -            if ('foreach' in options) {
194.3167 -                // Render once for each data point (treating data set as empty if shouldDisplay==false)
194.3168 -                var dataArray = (shouldDisplay && options['foreach']) || [];
194.3169 -                templateComputed = ko.renderTemplateForEach(templateName || element, dataArray, options, element, bindingContext);
194.3170 -            } else if (!shouldDisplay) {
194.3171 -                ko.virtualElements.emptyNode(element);
194.3172 -            } else {
194.3173 -                // Render once for this single data point (or use the viewModel if no data was provided)
194.3174 -                var innerBindingContext = ('data' in options) ?
194.3175 -                    bindingContext['createChildContext'](dataValue, options['as']) :  // Given an explitit 'data' value, we create a child binding context for it
194.3176 -                    bindingContext;                                                        // Given no explicit 'data' value, we retain the same binding context
194.3177 -                templateComputed = ko.renderTemplate(templateName || element, innerBindingContext, options, element);
194.3178 -            }
194.3179 -
194.3180 -            // It only makes sense to have a single template computed per element (otherwise which one should have its output displayed?)
194.3181 -            disposeOldComputedAndStoreNewOne(element, templateComputed);
194.3182 -        }
194.3183 -    };
194.3184 -
194.3185 -    // Anonymous templates can't be rewritten. Give a nice error message if you try to do it.
194.3186 -    ko.expressionRewriting.bindingRewriteValidators['template'] = function(bindingValue) {
194.3187 -        var parsedBindingValue = ko.expressionRewriting.parseObjectLiteral(bindingValue);
194.3188 -
194.3189 -        if ((parsedBindingValue.length == 1) && parsedBindingValue[0]['unknown'])
194.3190 -            return null; // It looks like a string literal, not an object literal, so treat it as a named template (which is allowed for rewriting)
194.3191 -
194.3192 -        if (ko.expressionRewriting.keyValueArrayContainsKey(parsedBindingValue, "name"))
194.3193 -            return null; // Named templates can be rewritten, so return "no error"
194.3194 -        return "This template engine does not support anonymous templates nested within its templates";
194.3195 -    };
194.3196 -
194.3197 -    ko.virtualElements.allowedBindings['template'] = true;
194.3198 -})();
194.3199 -
194.3200 -ko.exportSymbol('setTemplateEngine', ko.setTemplateEngine);
194.3201 -ko.exportSymbol('renderTemplate', ko.renderTemplate);
194.3202 -
194.3203 -ko.utils.compareArrays = (function () {
194.3204 -    var statusNotInOld = 'added', statusNotInNew = 'deleted';
194.3205 -
194.3206 -    // Simple calculation based on Levenshtein distance.
194.3207 -    function compareArrays(oldArray, newArray, dontLimitMoves) {
194.3208 -        oldArray = oldArray || [];
194.3209 -        newArray = newArray || [];
194.3210 -
194.3211 -        if (oldArray.length <= newArray.length)
194.3212 -            return compareSmallArrayToBigArray(oldArray, newArray, statusNotInOld, statusNotInNew, dontLimitMoves);
194.3213 -        else
194.3214 -            return compareSmallArrayToBigArray(newArray, oldArray, statusNotInNew, statusNotInOld, dontLimitMoves);
194.3215 -    }
194.3216 -
194.3217 -    function compareSmallArrayToBigArray(smlArray, bigArray, statusNotInSml, statusNotInBig, dontLimitMoves) {
194.3218 -        var myMin = Math.min,
194.3219 -            myMax = Math.max,
194.3220 -            editDistanceMatrix = [],
194.3221 -            smlIndex, smlIndexMax = smlArray.length,
194.3222 -            bigIndex, bigIndexMax = bigArray.length,
194.3223 -            compareRange = (bigIndexMax - smlIndexMax) || 1,
194.3224 -            maxDistance = smlIndexMax + bigIndexMax + 1,
194.3225 -            thisRow, lastRow,
194.3226 -            bigIndexMaxForRow, bigIndexMinForRow;
194.3227 -
194.3228 -        for (smlIndex = 0; smlIndex <= smlIndexMax; smlIndex++) {
194.3229 -            lastRow = thisRow;
194.3230 -            editDistanceMatrix.push(thisRow = []);
194.3231 -            bigIndexMaxForRow = myMin(bigIndexMax, smlIndex + compareRange);
194.3232 -            bigIndexMinForRow = myMax(0, smlIndex - 1);
194.3233 -            for (bigIndex = bigIndexMinForRow; bigIndex <= bigIndexMaxForRow; bigIndex++) {
194.3234 -                if (!bigIndex)
194.3235 -                    thisRow[bigIndex] = smlIndex + 1;
194.3236 -                else if (!smlIndex)  // Top row - transform empty array into new array via additions
194.3237 -                    thisRow[bigIndex] = bigIndex + 1;
194.3238 -                else if (smlArray[smlIndex - 1] === bigArray[bigIndex - 1])
194.3239 -                    thisRow[bigIndex] = lastRow[bigIndex - 1];                  // copy value (no edit)
194.3240 -                else {
194.3241 -                    var northDistance = lastRow[bigIndex] || maxDistance;       // not in big (deletion)
194.3242 -                    var westDistance = thisRow[bigIndex - 1] || maxDistance;    // not in small (addition)
194.3243 -                    thisRow[bigIndex] = myMin(northDistance, westDistance) + 1;
194.3244 -                }
194.3245 -            }
194.3246 -        }
194.3247 -
194.3248 -        var editScript = [], meMinusOne, notInSml = [], notInBig = [];
194.3249 -        for (smlIndex = smlIndexMax, bigIndex = bigIndexMax; smlIndex || bigIndex;) {
194.3250 -            meMinusOne = editDistanceMatrix[smlIndex][bigIndex] - 1;
194.3251 -            if (bigIndex && meMinusOne === editDistanceMatrix[smlIndex][bigIndex-1]) {
194.3252 -                notInSml.push(editScript[editScript.length] = {     // added
194.3253 -                    'status': statusNotInSml,
194.3254 -                    'value': bigArray[--bigIndex],
194.3255 -                    'index': bigIndex });
194.3256 -            } else if (smlIndex && meMinusOne === editDistanceMatrix[smlIndex - 1][bigIndex]) {
194.3257 -                notInBig.push(editScript[editScript.length] = {     // deleted
194.3258 -                    'status': statusNotInBig,
194.3259 -                    'value': smlArray[--smlIndex],
194.3260 -                    'index': smlIndex });
194.3261 -            } else {
194.3262 -                editScript.push({
194.3263 -                    'status': "retained",
194.3264 -                    'value': bigArray[--bigIndex] });
194.3265 -                --smlIndex;
194.3266 -            }
194.3267 -        }
194.3268 -
194.3269 -        if (notInSml.length && notInBig.length) {
194.3270 -            // Set a limit on the number of consecutive non-matching comparisons; having it a multiple of
194.3271 -            // smlIndexMax keeps the time complexity of this algorithm linear.
194.3272 -            var limitFailedCompares = smlIndexMax * 10, failedCompares,
194.3273 -                a, d, notInSmlItem, notInBigItem;
194.3274 -            // Go through the items that have been added and deleted and try to find matches between them.
194.3275 -            for (failedCompares = a = 0; (dontLimitMoves || failedCompares < limitFailedCompares) && (notInSmlItem = notInSml[a]); a++) {
194.3276 -                for (d = 0; notInBigItem = notInBig[d]; d++) {
194.3277 -                    if (notInSmlItem['value'] === notInBigItem['value']) {
194.3278 -                        notInSmlItem['moved'] = notInBigItem['index'];
194.3279 -                        notInBigItem['moved'] = notInSmlItem['index'];
194.3280 -                        notInBig.splice(d,1);       // This item is marked as moved; so remove it from notInBig list
194.3281 -                        failedCompares = d = 0;     // Reset failed compares count because we're checking for consecutive failures
194.3282 -                        break;
194.3283 -                    }
194.3284 -                }
194.3285 -                failedCompares += d;
194.3286 -            }
194.3287 -        }
194.3288 -        return editScript.reverse();
194.3289 -    }
194.3290 -
194.3291 -    return compareArrays;
194.3292 -})();
194.3293 -
194.3294 -ko.exportSymbol('utils.compareArrays', ko.utils.compareArrays);
194.3295 -
194.3296 -(function () {
194.3297 -    // Objective:
194.3298 -    // * Given an input array, a container DOM node, and a function from array elements to arrays of DOM nodes,
194.3299 -    //   map the array elements to arrays of DOM nodes, concatenate together all these arrays, and use them to populate the container DOM node
194.3300 -    // * Next time we're given the same combination of things (with the array possibly having mutated), update the container DOM node
194.3301 -    //   so that its children is again the concatenation of the mappings of the array elements, but don't re-map any array elements that we
194.3302 -    //   previously mapped - retain those nodes, and just insert/delete other ones
194.3303 -
194.3304 -    // "callbackAfterAddingNodes" will be invoked after any "mapping"-generated nodes are inserted into the container node
194.3305 -    // You can use this, for example, to activate bindings on those nodes.
194.3306 -
194.3307 -    function fixUpNodesToBeMovedOrRemoved(contiguousNodeArray) {
194.3308 -        // Before moving, deleting, or replacing a set of nodes that were previously outputted by the "map" function, we have to reconcile
194.3309 -        // them against what is in the DOM right now. It may be that some of the nodes have already been removed from the document,
194.3310 -        // or that new nodes might have been inserted in the middle, for example by a binding. Also, there may previously have been
194.3311 -        // leading comment nodes (created by rewritten string-based templates) that have since been removed during binding.
194.3312 -        // So, this function translates the old "map" output array into its best guess of what set of current DOM nodes should be removed.
194.3313 -        //
194.3314 -        // Rules:
194.3315 -        //   [A] Any leading nodes that aren't in the document any more should be ignored
194.3316 -        //       These most likely correspond to memoization nodes that were already removed during binding
194.3317 -        //       See https://github.com/SteveSanderson/knockout/pull/440
194.3318 -        //   [B] We want to output a contiguous series of nodes that are still in the document. So, ignore any nodes that
194.3319 -        //       have already been removed, and include any nodes that have been inserted among the previous collection
194.3320 -
194.3321 -        // Rule [A]
194.3322 -        while (contiguousNodeArray.length && !ko.utils.domNodeIsAttachedToDocument(contiguousNodeArray[0]))
194.3323 -            contiguousNodeArray.splice(0, 1);
194.3324 -
194.3325 -        // Rule [B]
194.3326 -        if (contiguousNodeArray.length > 1) {
194.3327 -            // Build up the actual new contiguous node set
194.3328 -            var current = contiguousNodeArray[0], last = contiguousNodeArray[contiguousNodeArray.length - 1], newContiguousSet = [current];
194.3329 -            while (current !== last) {
194.3330 -                current = current.nextSibling;
194.3331 -                if (!current) // Won't happen, except if the developer has manually removed some DOM elements (then we're in an undefined scenario)
194.3332 -                    return;
194.3333 -                newContiguousSet.push(current);
194.3334 -            }
194.3335 -
194.3336 -            // ... then mutate the input array to match this.
194.3337 -            // (The following line replaces the contents of contiguousNodeArray with newContiguousSet)
194.3338 -            Array.prototype.splice.apply(contiguousNodeArray, [0, contiguousNodeArray.length].concat(newContiguousSet));
194.3339 -        }
194.3340 -        return contiguousNodeArray;
194.3341 -    }
194.3342 -
194.3343 -    function mapNodeAndRefreshWhenChanged(containerNode, mapping, valueToMap, callbackAfterAddingNodes, index) {
194.3344 -        // Map this array value inside a dependentObservable so we re-map when any dependency changes
194.3345 -        var mappedNodes = [];
194.3346 -        var dependentObservable = ko.dependentObservable(function() {
194.3347 -            var newMappedNodes = mapping(valueToMap, index) || [];
194.3348 -
194.3349 -            // On subsequent evaluations, just replace the previously-inserted DOM nodes
194.3350 -            if (mappedNodes.length > 0) {
194.3351 -                ko.utils.replaceDomNodes(fixUpNodesToBeMovedOrRemoved(mappedNodes), newMappedNodes);
194.3352 -                if (callbackAfterAddingNodes)
194.3353 -                    ko.dependencyDetection.ignore(callbackAfterAddingNodes, null, [valueToMap, newMappedNodes, index]);
194.3354 -            }
194.3355 -
194.3356 -            // Replace the contents of the mappedNodes array, thereby updating the record
194.3357 -            // of which nodes would be deleted if valueToMap was itself later removed
194.3358 -            mappedNodes.splice(0, mappedNodes.length);
194.3359 -            ko.utils.arrayPushAll(mappedNodes, newMappedNodes);
194.3360 -        }, null, { disposeWhenNodeIsRemoved: containerNode, disposeWhen: function() { return (mappedNodes.length == 0) || !ko.utils.domNodeIsAttachedToDocument(mappedNodes[0]) } });
194.3361 -        return { mappedNodes : mappedNodes, dependentObservable : (dependentObservable.isActive() ? dependentObservable : undefined) };
194.3362 -    }
194.3363 -
194.3364 -    var lastMappingResultDomDataKey = "setDomNodeChildrenFromArrayMapping_lastMappingResult";
194.3365 -
194.3366 -    ko.utils.setDomNodeChildrenFromArrayMapping = function (domNode, array, mapping, options, callbackAfterAddingNodes) {
194.3367 -        // Compare the provided array against the previous one
194.3368 -        array = array || [];
194.3369 -        options = options || {};
194.3370 -        var isFirstExecution = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) === undefined;
194.3371 -        var lastMappingResult = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) || [];
194.3372 -        var lastArray = ko.utils.arrayMap(lastMappingResult, function (x) { return x.arrayEntry; });
194.3373 -        var editScript = ko.utils.compareArrays(lastArray, array);
194.3374 -
194.3375 -        // Build the new mapping result
194.3376 -        var newMappingResult = [];
194.3377 -        var lastMappingResultIndex = 0;
194.3378 -        var newMappingResultIndex = 0;
194.3379 -
194.3380 -        var nodesToDelete = [];
194.3381 -        var itemsToProcess = [];
194.3382 -        var itemsForBeforeRemoveCallbacks = [];
194.3383 -        var itemsForMoveCallbacks = [];
194.3384 -        var itemsForAfterAddCallbacks = [];
194.3385 -        var mapData;
194.3386 -
194.3387 -        function itemMovedOrRetained(editScriptIndex, oldPosition) {
194.3388 -            mapData = lastMappingResult[oldPosition];
194.3389 -            if (newMappingResultIndex !== oldPosition)
194.3390 -                itemsForMoveCallbacks[editScriptIndex] = mapData;
194.3391 -            // Since updating the index might change the nodes, do so before calling fixUpNodesToBeMovedOrRemoved
194.3392 -            mapData.indexObservable(newMappingResultIndex++);
194.3393 -            fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes);
194.3394 -            newMappingResult.push(mapData);
194.3395 -            itemsToProcess.push(mapData);
194.3396 -        }
194.3397 -
194.3398 -        function callCallback(callback, items) {
194.3399 -            if (callback) {
194.3400 -                for (var i = 0, n = items.length; i < n; i++) {
194.3401 -                    if (items[i]) {
194.3402 -                        ko.utils.arrayForEach(items[i].mappedNodes, function(node) {
194.3403 -                            callback(node, i, items[i].arrayEntry);
194.3404 -                        });
194.3405 -                    }
194.3406 -                }
194.3407 -            }
194.3408 -        }
194.3409 -
194.3410 -        for (var i = 0, editScriptItem, movedIndex; editScriptItem = editScript[i]; i++) {
194.3411 -            movedIndex = editScriptItem['moved'];
194.3412 -            switch (editScriptItem['status']) {
194.3413 -                case "deleted":
194.3414 -                    if (movedIndex === undefined) {
194.3415 -                        mapData = lastMappingResult[lastMappingResultIndex];
194.3416 -
194.3417 -                        // Stop tracking changes to the mapping for these nodes
194.3418 -                        if (mapData.dependentObservable)
194.3419 -                            mapData.dependentObservable.dispose();
194.3420 -
194.3421 -                        // Queue these nodes for later removal
194.3422 -                        nodesToDelete.push.apply(nodesToDelete, fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes));
194.3423 -                        if (options['beforeRemove']) {
194.3424 -                            itemsForBeforeRemoveCallbacks[i] = mapData;
194.3425 -                            itemsToProcess.push(mapData);
194.3426 -                        }
194.3427 -                    }
194.3428 -                    lastMappingResultIndex++;
194.3429 -                    break;
194.3430 -
194.3431 -                case "retained":
194.3432 -                    itemMovedOrRetained(i, lastMappingResultIndex++);
194.3433 -                    break;
194.3434 -
194.3435 -                case "added":
194.3436 -                    if (movedIndex !== undefined) {
194.3437 -                        itemMovedOrRetained(i, movedIndex);
194.3438 -                    } else {
194.3439 -                        mapData = { arrayEntry: editScriptItem['value'], indexObservable: ko.observable(newMappingResultIndex++) };
194.3440 -                        newMappingResult.push(mapData);
194.3441 -                        itemsToProcess.push(mapData);
194.3442 -                        if (!isFirstExecution)
194.3443 -                            itemsForAfterAddCallbacks[i] = mapData;
194.3444 -                    }
194.3445 -                    break;
194.3446 -            }
194.3447 -        }
194.3448 -
194.3449 -        // Call beforeMove first before any changes have been made to the DOM
194.3450 -        callCallback(options['beforeMove'], itemsForMoveCallbacks);
194.3451 -
194.3452 -        // Next remove nodes for deleted items (or just clean if there's a beforeRemove callback)
194.3453 -        ko.utils.arrayForEach(nodesToDelete, options['beforeRemove'] ? ko.cleanNode : ko.removeNode);
194.3454 -
194.3455 -        // Next add/reorder the remaining items (will include deleted items if there's a beforeRemove callback)
194.3456 -        for (var i = 0, nextNode = ko.virtualElements.firstChild(domNode), lastNode, node; mapData = itemsToProcess[i]; i++) {
194.3457 -            // Get nodes for newly added items
194.3458 -            if (!mapData.mappedNodes)
194.3459 -                ko.utils.extend(mapData, mapNodeAndRefreshWhenChanged(domNode, mapping, mapData.arrayEntry, callbackAfterAddingNodes, mapData.indexObservable));
194.3460 -
194.3461 -            // Put nodes in the right place if they aren't there already
194.3462 -            for (var j = 0; node = mapData.mappedNodes[j]; nextNode = node.nextSibling, lastNode = node, j++) {
194.3463 -                if (node !== nextNode)
194.3464 -                    ko.virtualElements.insertAfter(domNode, node, lastNode);
194.3465 -            }
194.3466 -
194.3467 -            // Run the callbacks for newly added nodes (for example, to apply bindings, etc.)
194.3468 -            if (!mapData.initialized && callbackAfterAddingNodes) {
194.3469 -                callbackAfterAddingNodes(mapData.arrayEntry, mapData.mappedNodes, mapData.indexObservable);
194.3470 -                mapData.initialized = true;
194.3471 -            }
194.3472 -        }
194.3473 -
194.3474 -        // If there's a beforeRemove callback, call it after reordering.
194.3475 -        // Note that we assume that the beforeRemove callback will usually be used to remove the nodes using
194.3476 -        // some sort of animation, which is why we first reorder the nodes that will be removed. If the
194.3477 -        // callback instead removes the nodes right away, it would be more efficient to skip reordering them.
194.3478 -        // Perhaps we'll make that change in the future if this scenario becomes more common.
194.3479 -        callCallback(options['beforeRemove'], itemsForBeforeRemoveCallbacks);
194.3480 -
194.3481 -        // Finally call afterMove and afterAdd callbacks
194.3482 -        callCallback(options['afterMove'], itemsForMoveCallbacks);
194.3483 -        callCallback(options['afterAdd'], itemsForAfterAddCallbacks);
194.3484 -
194.3485 -        // Store a copy of the array items we just considered so we can difference it next time
194.3486 -        ko.utils.domData.set(domNode, lastMappingResultDomDataKey, newMappingResult);
194.3487 -    }
194.3488 -})();
194.3489 -
194.3490 -ko.exportSymbol('utils.setDomNodeChildrenFromArrayMapping', ko.utils.setDomNodeChildrenFromArrayMapping);
194.3491 -ko.nativeTemplateEngine = function () {
194.3492 -    this['allowTemplateRewriting'] = false;
194.3493 -}
194.3494 -
194.3495 -ko.nativeTemplateEngine.prototype = new ko.templateEngine();
194.3496 -ko.nativeTemplateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
194.3497 -    var useNodesIfAvailable = !(ko.utils.ieVersion < 9), // IE<9 cloneNode doesn't work properly
194.3498 -        templateNodesFunc = useNodesIfAvailable ? templateSource['nodes'] : null,
194.3499 -        templateNodes = templateNodesFunc ? templateSource['nodes']() : null;
194.3500 -
194.3501 -    if (templateNodes) {
194.3502 -        return ko.utils.makeArray(templateNodes.cloneNode(true).childNodes);
194.3503 -    } else {
194.3504 -        var templateText = templateSource['text']();
194.3505 -        return ko.utils.parseHtmlFragment(templateText);
194.3506 -    }
194.3507 -};
194.3508 -
194.3509 -ko.nativeTemplateEngine.instance = new ko.nativeTemplateEngine();
194.3510 -ko.setTemplateEngine(ko.nativeTemplateEngine.instance);
194.3511 -
194.3512 -ko.exportSymbol('nativeTemplateEngine', ko.nativeTemplateEngine);
194.3513 -(function() {
194.3514 -    ko.jqueryTmplTemplateEngine = function () {
194.3515 -        // Detect which version of jquery-tmpl you're using. Unfortunately jquery-tmpl
194.3516 -        // doesn't expose a version number, so we have to infer it.
194.3517 -        // Note that as of Knockout 1.3, we only support jQuery.tmpl 1.0.0pre and later,
194.3518 -        // which KO internally refers to as version "2", so older versions are no longer detected.
194.3519 -        var jQueryTmplVersion = this.jQueryTmplVersion = (function() {
194.3520 -            if ((typeof(jQuery) == "undefined") || !(jQuery['tmpl']))
194.3521 -                return 0;
194.3522 -            // Since it exposes no official version number, we use our own numbering system. To be updated as jquery-tmpl evolves.
194.3523 -            try {
194.3524 -                if (jQuery['tmpl']['tag']['tmpl']['open'].toString().indexOf('__') >= 0) {
194.3525 -                    // Since 1.0.0pre, custom tags should append markup to an array called "__"
194.3526 -                    return 2; // Final version of jquery.tmpl
194.3527 -                }
194.3528 -            } catch(ex) { /* Apparently not the version we were looking for */ }
194.3529 -
194.3530 -            return 1; // Any older version that we don't support
194.3531 -        })();
194.3532 -
194.3533 -        function ensureHasReferencedJQueryTemplates() {
194.3534 -            if (jQueryTmplVersion < 2)
194.3535 -                throw new Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");
194.3536 -        }
194.3537 -
194.3538 -        function executeTemplate(compiledTemplate, data, jQueryTemplateOptions) {
194.3539 -            return jQuery['tmpl'](compiledTemplate, data, jQueryTemplateOptions);
194.3540 -        }
194.3541 -
194.3542 -        this['renderTemplateSource'] = function(templateSource, bindingContext, options) {
194.3543 -            options = options || {};
194.3544 -            ensureHasReferencedJQueryTemplates();
194.3545 -
194.3546 -            // Ensure we have stored a precompiled version of this template (don't want to reparse on every render)
194.3547 -            var precompiled = templateSource['data']('precompiled');
194.3548 -            if (!precompiled) {
194.3549 -                var templateText = templateSource['text']() || "";
194.3550 -                // Wrap in "with($whatever.koBindingContext) { ... }"
194.3551 -                templateText = "{{ko_with $item.koBindingContext}}" + templateText + "{{/ko_with}}";
194.3552 -
194.3553 -                precompiled = jQuery['template'](null, templateText);
194.3554 -                templateSource['data']('precompiled', precompiled);
194.3555 -            }
194.3556 -
194.3557 -            var data = [bindingContext['$data']]; // Prewrap the data in an array to stop jquery.tmpl from trying to unwrap any arrays
194.3558 -            var jQueryTemplateOptions = jQuery['extend']({ 'koBindingContext': bindingContext }, options['templateOptions']);
194.3559 -
194.3560 -            var resultNodes = executeTemplate(precompiled, data, jQueryTemplateOptions);
194.3561 -            resultNodes['appendTo'](document.createElement("div")); // Using "appendTo" forces jQuery/jQuery.tmpl to perform necessary cleanup work
194.3562 -
194.3563 -            jQuery['fragments'] = {}; // Clear jQuery's fragment cache to avoid a memory leak after a large number of template renders
194.3564 -            return resultNodes;
194.3565 -        };
194.3566 -
194.3567 -        this['createJavaScriptEvaluatorBlock'] = function(script) {
194.3568 -            return "{{ko_code ((function() { return " + script + " })()) }}";
194.3569 -        };
194.3570 -
194.3571 -        this['addTemplate'] = function(templateName, templateMarkup) {
194.3572 -            document.write("<script type='text/html' id='" + templateName + "'>" + templateMarkup + "</script>");
194.3573 -        };
194.3574 -
194.3575 -        if (jQueryTmplVersion > 0) {
194.3576 -            jQuery['tmpl']['tag']['ko_code'] = {
194.3577 -                open: "__.push($1 || '');"
194.3578 -            };
194.3579 -            jQuery['tmpl']['tag']['ko_with'] = {
194.3580 -                open: "with($1) {",
194.3581 -                close: "} "
194.3582 -            };
194.3583 -        }
194.3584 -    };
194.3585 -
194.3586 -    ko.jqueryTmplTemplateEngine.prototype = new ko.templateEngine();
194.3587 -
194.3588 -    // Use this one by default *only if jquery.tmpl is referenced*
194.3589 -    var jqueryTmplTemplateEngineInstance = new ko.jqueryTmplTemplateEngine();
194.3590 -    if (jqueryTmplTemplateEngineInstance.jQueryTmplVersion > 0)
194.3591 -        ko.setTemplateEngine(jqueryTmplTemplateEngineInstance);
194.3592 -
194.3593 -    ko.exportSymbol('jqueryTmplTemplateEngine', ko.jqueryTmplTemplateEngine);
194.3594 -})();
194.3595 -});
194.3596 -})(window,document,navigator,window["jQuery"]);
194.3597 -})();
194.3598 \ No newline at end of file
   195.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   195.2 +++ b/ko-fx/src/main/resources/org/netbeans/html/kofx/knockout-2.2.1.js	Tue Jan 07 08:21:57 2014 +0100
   195.3 @@ -0,0 +1,3594 @@
   195.4 +// Knockout JavaScript library v2.2.1
   195.5 +// (c) Steven Sanderson - http://knockoutjs.com/
   195.6 +// License: MIT (http://www.opensource.org/licenses/mit-license.php)
   195.7 +
   195.8 +(function(){
   195.9 +var DEBUG=true;
  195.10 +(function(window,document,navigator,jQuery,undefined){
  195.11 +!function(factory) {
  195.12 +    // Support three module loading scenarios
  195.13 +    if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
  195.14 +        // [1] CommonJS/Node.js
  195.15 +        var target = module['exports'] || exports; // module.exports is for Node.js
  195.16 +        factory(target);
  195.17 +    } else if (typeof define === 'function' && define['amd']) {
  195.18 +        // [2] AMD anonymous module
  195.19 +        define(['exports'], factory);
  195.20 +    } else {
  195.21 +        // [3] No module loader (plain <script> tag) - put directly in global namespace
  195.22 +        factory(window['ko'] = {});
  195.23 +    }
  195.24 +}(function(koExports){
  195.25 +// Internally, all KO objects are attached to koExports (even the non-exported ones whose names will be minified by the closure compiler).
  195.26 +// In the future, the following "ko" variable may be made distinct from "koExports" so that private objects are not externally reachable.
  195.27 +var ko = typeof koExports !== 'undefined' ? koExports : {};
  195.28 +// Google Closure Compiler helpers (used only to make the minified file smaller)
  195.29 +ko.exportSymbol = function(koPath, object) {
  195.30 +	var tokens = koPath.split(".");
  195.31 +
  195.32 +	// In the future, "ko" may become distinct from "koExports" (so that non-exported objects are not reachable)
  195.33 +	// At that point, "target" would be set to: (typeof koExports !== "undefined" ? koExports : ko)
  195.34 +	var target = ko;
  195.35 +
  195.36 +	for (var i = 0; i < tokens.length - 1; i++)
  195.37 +		target = target[tokens[i]];
  195.38 +	target[tokens[tokens.length - 1]] = object;
  195.39 +};
  195.40 +ko.exportProperty = function(owner, publicName, object) {
  195.41 +  owner[publicName] = object;
  195.42 +};
  195.43 +ko.version = "2.2.1";
  195.44 +
  195.45 +ko.exportSymbol('version', ko.version);
  195.46 +ko.utils = new (function () {
  195.47 +    var stringTrimRegex = /^(\s|\u00A0)+|(\s|\u00A0)+$/g;
  195.48 +
  195.49 +    // Represent the known event types in a compact way, then at runtime transform it into a hash with event name as key (for fast lookup)
  195.50 +    var knownEvents = {}, knownEventTypesByEventName = {};
  195.51 +    var keyEventTypeName = /Firefox\/2/i.test(navigator.userAgent) ? 'KeyboardEvent' : 'UIEvents';
  195.52 +    knownEvents[keyEventTypeName] = ['keyup', 'keydown', 'keypress'];
  195.53 +    knownEvents['MouseEvents'] = ['click', 'dblclick', 'mousedown', 'mouseup', 'mousemove', 'mouseover', 'mouseout', 'mouseenter', 'mouseleave'];
  195.54 +    for (var eventType in knownEvents) {
  195.55 +        var knownEventsForType = knownEvents[eventType];
  195.56 +        if (knownEventsForType.length) {
  195.57 +            for (var i = 0, j = knownEventsForType.length; i < j; i++)
  195.58 +                knownEventTypesByEventName[knownEventsForType[i]] = eventType;
  195.59 +        }
  195.60 +    }
  195.61 +    var eventsThatMustBeRegisteredUsingAttachEvent = { 'propertychange': true }; // Workaround for an IE9 issue - https://github.com/SteveSanderson/knockout/issues/406
  195.62 +
  195.63 +    // Detect IE versions for bug workarounds (uses IE conditionals, not UA string, for robustness)
  195.64 +    // Note that, since IE 10 does not support conditional comments, the following logic only detects IE < 10.
  195.65 +    // Currently this is by design, since IE 10+ behaves correctly when treated as a standard browser.
  195.66 +    // If there is a future need to detect specific versions of IE10+, we will amend this.
  195.67 +    var ieVersion = (function() {
  195.68 +        var version = 3, div = document.createElement('div'), iElems = div.getElementsByTagName('i');
  195.69 +
  195.70 +        // Keep constructing conditional HTML blocks until we hit one that resolves to an empty fragment
  195.71 +        while (
  195.72 +            div.innerHTML = '<!--[if gt IE ' + (++version) + ']><i></i><![endif]-->',
  195.73 +            iElems[0]
  195.74 +        );
  195.75 +        return version > 4 ? version : undefined;
  195.76 +    }());
  195.77 +    var isIe6 = ieVersion === 6,
  195.78 +        isIe7 = ieVersion === 7;
  195.79 +
  195.80 +    function isClickOnCheckableElement(element, eventType) {
  195.81 +        if ((ko.utils.tagNameLower(element) !== "input") || !element.type) return false;
  195.82 +        if (eventType.toLowerCase() != "click") return false;
  195.83 +        var inputType = element.type;
  195.84 +        return (inputType == "checkbox") || (inputType == "radio");
  195.85 +    }
  195.86 +
  195.87 +    return {
  195.88 +        fieldsIncludedWithJsonPost: ['authenticity_token', /^__RequestVerificationToken(_.*)?$/],
  195.89 +
  195.90 +        arrayForEach: function (array, action) {
  195.91 +            for (var i = 0, j = array.length; i < j; i++)
  195.92 +                action(array[i]);
  195.93 +        },
  195.94 +
  195.95 +        arrayIndexOf: function (array, item) {
  195.96 +            if (typeof Array.prototype.indexOf == "function")
  195.97 +                return Array.prototype.indexOf.call(array, item);
  195.98 +            for (var i = 0, j = array.length; i < j; i++)
  195.99 +                if (array[i] === item)
 195.100 +                    return i;
 195.101 +            return -1;
 195.102 +        },
 195.103 +
 195.104 +        arrayFirst: function (array, predicate, predicateOwner) {
 195.105 +            for (var i = 0, j = array.length; i < j; i++)
 195.106 +                if (predicate.call(predicateOwner, array[i]))
 195.107 +                    return array[i];
 195.108 +            return null;
 195.109 +        },
 195.110 +
 195.111 +        arrayRemoveItem: function (array, itemToRemove) {
 195.112 +            var index = ko.utils.arrayIndexOf(array, itemToRemove);
 195.113 +            if (index >= 0)
 195.114 +                array.splice(index, 1);
 195.115 +        },
 195.116 +
 195.117 +        arrayGetDistinctValues: function (array) {
 195.118 +            array = array || [];
 195.119 +            var result = [];
 195.120 +            for (var i = 0, j = array.length; i < j; i++) {
 195.121 +                if (ko.utils.arrayIndexOf(result, array[i]) < 0)
 195.122 +                    result.push(array[i]);
 195.123 +            }
 195.124 +            return result;
 195.125 +        },
 195.126 +
 195.127 +        arrayMap: function (array, mapping) {
 195.128 +            array = array || [];
 195.129 +            var result = [];
 195.130 +            for (var i = 0, j = array.length; i < j; i++)
 195.131 +                result.push(mapping(array[i]));
 195.132 +            return result;
 195.133 +        },
 195.134 +
 195.135 +        arrayFilter: function (array, predicate) {
 195.136 +            array = array || [];
 195.137 +            var result = [];
 195.138 +            for (var i = 0, j = array.length; i < j; i++)
 195.139 +                if (predicate(array[i]))
 195.140 +                    result.push(array[i]);
 195.141 +            return result;
 195.142 +        },
 195.143 +
 195.144 +        arrayPushAll: function (array, valuesToPush) {
 195.145 +            if (valuesToPush instanceof Array)
 195.146 +                array.push.apply(array, valuesToPush);
 195.147 +            else
 195.148 +                for (var i = 0, j = valuesToPush.length; i < j; i++)
 195.149 +                    array.push(valuesToPush[i]);
 195.150 +            return array;
 195.151 +        },
 195.152 +
 195.153 +        extend: function (target, source) {
 195.154 +            if (source) {
 195.155 +                for(var prop in source) {
 195.156 +                    if(source.hasOwnProperty(prop)) {
 195.157 +                        target[prop] = source[prop];
 195.158 +                    }
 195.159 +                }
 195.160 +            }
 195.161 +            return target;
 195.162 +        },
 195.163 +
 195.164 +        emptyDomNode: function (domNode) {
 195.165 +            while (domNode.firstChild) {
 195.166 +                ko.removeNode(domNode.firstChild);
 195.167 +            }
 195.168 +        },
 195.169 +
 195.170 +        moveCleanedNodesToContainerElement: function(nodes) {
 195.171 +            // Ensure it's a real array, as we're about to reparent the nodes and
 195.172 +            // we don't want the underlying collection to change while we're doing that.
 195.173 +            var nodesArray = ko.utils.makeArray(nodes);
 195.174 +
 195.175 +            var container = document.createElement('div');
 195.176 +            for (var i = 0, j = nodesArray.length; i < j; i++) {
 195.177 +                container.appendChild(ko.cleanNode(nodesArray[i]));
 195.178 +            }
 195.179 +            return container;
 195.180 +        },
 195.181 +
 195.182 +        cloneNodes: function (nodesArray, shouldCleanNodes) {
 195.183 +            for (var i = 0, j = nodesArray.length, newNodesArray = []; i < j; i++) {
 195.184 +                var clonedNode = nodesArray[i].cloneNode(true);
 195.185 +                newNodesArray.push(shouldCleanNodes ? ko.cleanNode(clonedNode) : clonedNode);
 195.186 +            }
 195.187 +            return newNodesArray;
 195.188 +        },
 195.189 +
 195.190 +        setDomNodeChildren: function (domNode, childNodes) {
 195.191 +            ko.utils.emptyDomNode(domNode);
 195.192 +            if (childNodes) {
 195.193 +                for (var i = 0, j = childNodes.length; i < j; i++)
 195.194 +                    domNode.appendChild(childNodes[i]);
 195.195 +            }
 195.196 +        },
 195.197 +
 195.198 +        replaceDomNodes: function (nodeToReplaceOrNodeArray, newNodesArray) {
 195.199 +            var nodesToReplaceArray = nodeToReplaceOrNodeArray.nodeType ? [nodeToReplaceOrNodeArray] : nodeToReplaceOrNodeArray;
 195.200 +            if (nodesToReplaceArray.length > 0) {
 195.201 +                var insertionPoint = nodesToReplaceArray[0];
 195.202 +                var parent = insertionPoint.parentNode;
 195.203 +                for (var i = 0, j = newNodesArray.length; i < j; i++)
 195.204 +                    parent.insertBefore(newNodesArray[i], insertionPoint);
 195.205 +                for (var i = 0, j = nodesToReplaceArray.length; i < j; i++) {
 195.206 +                    ko.removeNode(nodesToReplaceArray[i]);
 195.207 +                }
 195.208 +            }
 195.209 +        },
 195.210 +
 195.211 +        setOptionNodeSelectionState: function (optionNode, isSelected) {
 195.212 +            // IE6 sometimes throws "unknown error" if you try to write to .selected directly, whereas Firefox struggles with setAttribute. Pick one based on browser.
 195.213 +            if (ieVersion < 7)
 195.214 +                optionNode.setAttribute("selected", isSelected);
 195.215 +            else
 195.216 +                optionNode.selected = isSelected;
 195.217 +        },
 195.218 +
 195.219 +        stringTrim: function (string) {
 195.220 +            return (string || "").replace(stringTrimRegex, "");
 195.221 +        },
 195.222 +
 195.223 +        stringTokenize: function (string, delimiter) {
 195.224 +            var result = [];
 195.225 +            var tokens = (string || "").split(delimiter);
 195.226 +            for (var i = 0, j = tokens.length; i < j; i++) {
 195.227 +                var trimmed = ko.utils.stringTrim(tokens[i]);
 195.228 +                if (trimmed !== "")
 195.229 +                    result.push(trimmed);
 195.230 +            }
 195.231 +            return result;
 195.232 +        },
 195.233 +
 195.234 +        stringStartsWith: function (string, startsWith) {
 195.235 +            string = string || "";
 195.236 +            if (startsWith.length > string.length)
 195.237 +                return false;
 195.238 +            return string.substring(0, startsWith.length) === startsWith;
 195.239 +        },
 195.240 +
 195.241 +        domNodeIsContainedBy: function (node, containedByNode) {
 195.242 +            if (containedByNode.compareDocumentPosition)
 195.243 +                return (containedByNode.compareDocumentPosition(node) & 16) == 16;
 195.244 +            while (node != null) {
 195.245 +                if (node == containedByNode)
 195.246 +                    return true;
 195.247 +                node = node.parentNode;
 195.248 +            }
 195.249 +            return false;
 195.250 +        },
 195.251 +
 195.252 +        domNodeIsAttachedToDocument: function (node) {
 195.253 +            return ko.utils.domNodeIsContainedBy(node, node.ownerDocument);
 195.254 +        },
 195.255 +
 195.256 +        tagNameLower: function(element) {
 195.257 +            // For HTML elements, tagName will always be upper case; for XHTML elements, it'll be lower case.
 195.258 +            // Possible future optimization: If we know it's an element from an XHTML document (not HTML),
 195.259 +            // we don't need to do the .toLowerCase() as it will always be lower case anyway.
 195.260 +            return element && element.tagName && element.tagName.toLowerCase();
 195.261 +        },
 195.262 +
 195.263 +        registerEventHandler: function (element, eventType, handler) {
 195.264 +            var mustUseAttachEvent = ieVersion && eventsThatMustBeRegisteredUsingAttachEvent[eventType];
 195.265 +            if (!mustUseAttachEvent && typeof jQuery != "undefined") {
 195.266 +                if (isClickOnCheckableElement(element, eventType)) {
 195.267 +                    // For click events on checkboxes, jQuery interferes with the event handling in an awkward way:
 195.268 +                    // it toggles the element checked state *after* the click event handlers run, whereas native
 195.269 +                    // click events toggle the checked state *before* the event handler.
 195.270 +                    // Fix this by intecepting the handler and applying the correct checkedness before it runs.
 195.271 +                    var originalHandler = handler;
 195.272 +                    handler = function(event, eventData) {
 195.273 +                        var jQuerySuppliedCheckedState = this.checked;
 195.274 +                        if (eventData)
 195.275 +                            this.checked = eventData.checkedStateBeforeEvent !== true;
 195.276 +                        originalHandler.call(this, event);
 195.277 +                        this.checked = jQuerySuppliedCheckedState; // Restore the state jQuery applied
 195.278 +                    };
 195.279 +                }
 195.280 +                jQuery(element)['bind'](eventType, handler);
 195.281 +            } else if (!mustUseAttachEvent && typeof element.addEventListener == "function")
 195.282 +                element.addEventListener(eventType, handler, false);
 195.283 +            else if (typeof element.attachEvent != "undefined")
 195.284 +                element.attachEvent("on" + eventType, function (event) {
 195.285 +                    handler.call(element, event);
 195.286 +                });
 195.287 +            else
 195.288 +                throw new Error("Browser doesn't support addEventListener or attachEvent");
 195.289 +        },
 195.290 +
 195.291 +        triggerEvent: function (element, eventType) {
 195.292 +            if (!(element && element.nodeType))
 195.293 +                throw new Error("element must be a DOM node when calling triggerEvent");
 195.294 +
 195.295 +            if (typeof jQuery != "undefined") {
 195.296 +                var eventData = [];
 195.297 +                if (isClickOnCheckableElement(element, eventType)) {
 195.298 +                    // Work around the jQuery "click events on checkboxes" issue described above by storing the original checked state before triggering the handler
 195.299 +                    eventData.push({ checkedStateBeforeEvent: element.checked });
 195.300 +                }
 195.301 +                jQuery(element)['trigger'](eventType, eventData);
 195.302 +            } else if (typeof document.createEvent == "function") {
 195.303 +                if (typeof element.dispatchEvent == "function") {
 195.304 +                    var eventCategory = knownEventTypesByEventName[eventType] || "HTMLEvents";
 195.305 +                    var event = document.createEvent(eventCategory);
 195.306 +                    event.initEvent(eventType, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, element);
 195.307 +                    element.dispatchEvent(event);
 195.308 +                }
 195.309 +                else
 195.310 +                    throw new Error("The supplied element doesn't support dispatchEvent");
 195.311 +            } else if (typeof element.fireEvent != "undefined") {
 195.312 +                // Unlike other browsers, IE doesn't change the checked state of checkboxes/radiobuttons when you trigger their "click" event
 195.313 +                // so to make it consistent, we'll do it manually here
 195.314 +                if (isClickOnCheckableElement(element, eventType))
 195.315 +                    element.checked = element.checked !== true;
 195.316 +                element.fireEvent("on" + eventType);
 195.317 +            }
 195.318 +            else
 195.319 +                throw new Error("Browser doesn't support triggering events");
 195.320 +        },
 195.321 +
 195.322 +        unwrapObservable: function (value) {
 195.323 +            return ko.isObservable(value) ? value() : value;
 195.324 +        },
 195.325 +
 195.326 +        peekObservable: function (value) {
 195.327 +            return ko.isObservable(value) ? value.peek() : value;
 195.328 +        },
 195.329 +
 195.330 +        toggleDomNodeCssClass: function (node, classNames, shouldHaveClass) {
 195.331 +            if (classNames) {
 195.332 +                var cssClassNameRegex = /[\w-]+/g,
 195.333 +                    currentClassNames = node.className.match(cssClassNameRegex) || [];
 195.334 +                ko.utils.arrayForEach(classNames.match(cssClassNameRegex), function(className) {
 195.335 +                    var indexOfClass = ko.utils.arrayIndexOf(currentClassNames, className);
 195.336 +                    if (indexOfClass >= 0) {
 195.337 +                        if (!shouldHaveClass)
 195.338 +                            currentClassNames.splice(indexOfClass, 1);
 195.339 +                    } else {
 195.340 +                        if (shouldHaveClass)
 195.341 +                            currentClassNames.push(className);
 195.342 +                    }
 195.343 +                });
 195.344 +                node.className = currentClassNames.join(" ");
 195.345 +            }
 195.346 +        },
 195.347 +
 195.348 +        setTextContent: function(element, textContent) {
 195.349 +            var value = ko.utils.unwrapObservable(textContent);
 195.350 +            if ((value === null) || (value === undefined))
 195.351 +                value = "";
 195.352 +
 195.353 +            if (element.nodeType === 3) {
 195.354 +                element.data = value;
 195.355 +            } else {
 195.356 +                // We need there to be exactly one child: a text node.
 195.357 +                // If there are no children, more than one, or if it's not a text node,
 195.358 +                // we'll clear everything and create a single text node.
 195.359 +                var innerTextNode = ko.virtualElements.firstChild(element);
 195.360 +                if (!innerTextNode || innerTextNode.nodeType != 3 || ko.virtualElements.nextSibling(innerTextNode)) {
 195.361 +                    ko.virtualElements.setDomNodeChildren(element, [document.createTextNode(value)]);
 195.362 +                } else {
 195.363 +                    innerTextNode.data = value;
 195.364 +                }
 195.365 +
 195.366 +                ko.utils.forceRefresh(element);
 195.367 +            }
 195.368 +        },
 195.369 +
 195.370 +        setElementName: function(element, name) {
 195.371 +            element.name = name;
 195.372 +
 195.373 +            // Workaround IE 6/7 issue
 195.374 +            // - https://github.com/SteveSanderson/knockout/issues/197
 195.375 +            // - http://www.matts411.com/post/setting_the_name_attribute_in_ie_dom/
 195.376 +            if (ieVersion <= 7) {
 195.377 +                try {
 195.378 +                    element.mergeAttributes(document.createElement("<input name='" + element.name + "'/>"), false);
 195.379 +                }
 195.380 +                catch(e) {} // For IE9 with doc mode "IE9 Standards" and browser mode "IE9 Compatibility View"
 195.381 +            }
 195.382 +        },
 195.383 +
 195.384 +        forceRefresh: function(node) {
 195.385 +            // Workaround for an IE9 rendering bug - https://github.com/SteveSanderson/knockout/issues/209
 195.386 +            if (ieVersion >= 9) {
 195.387 +                // For text nodes and comment nodes (most likely virtual elements), we will have to refresh the container
 195.388 +                var elem = node.nodeType == 1 ? node : node.parentNode;
 195.389 +                if (elem.style)
 195.390 +                    elem.style.zoom = elem.style.zoom;
 195.391 +            }
 195.392 +        },
 195.393 +
 195.394 +        ensureSelectElementIsRenderedCorrectly: function(selectElement) {
 195.395 +            // Workaround for IE9 rendering bug - it doesn't reliably display all the text in dynamically-added select boxes unless you force it to re-render by updating the width.
 195.396 +            // (See https://github.com/SteveSanderson/knockout/issues/312, http://stackoverflow.com/questions/5908494/select-only-shows-first-char-of-selected-option)
 195.397 +            if (ieVersion >= 9) {
 195.398 +                var originalWidth = selectElement.style.width;
 195.399 +                selectElement.style.width = 0;
 195.400 +                selectElement.style.width = originalWidth;
 195.401 +            }
 195.402 +        },
 195.403 +
 195.404 +        range: function (min, max) {
 195.405 +            min = ko.utils.unwrapObservable(min);
 195.406 +            max = ko.utils.unwrapObservable(max);
 195.407 +            var result = [];
 195.408 +            for (var i = min; i <= max; i++)
 195.409 +                result.push(i);
 195.410 +            return result;
 195.411 +        },
 195.412 +
 195.413 +        makeArray: function(arrayLikeObject) {
 195.414 +            var result = [];
 195.415 +            for (var i = 0, j = arrayLikeObject.length; i < j; i++) {
 195.416 +                result.push(arrayLikeObject[i]);
 195.417 +            };
 195.418 +            return result;
 195.419 +        },
 195.420 +
 195.421 +        isIe6 : isIe6,
 195.422 +        isIe7 : isIe7,
 195.423 +        ieVersion : ieVersion,
 195.424 +
 195.425 +        getFormFields: function(form, fieldName) {
 195.426 +            var fields = ko.utils.makeArray(form.getElementsByTagName("input")).concat(ko.utils.makeArray(form.getElementsByTagName("textarea")));
 195.427 +            var isMatchingField = (typeof fieldName == 'string')
 195.428 +                ? function(field) { return field.name === fieldName }
 195.429 +                : function(field) { return fieldName.test(field.name) }; // Treat fieldName as regex or object containing predicate
 195.430 +            var matches = [];
 195.431 +            for (var i = fields.length - 1; i >= 0; i--) {
 195.432 +                if (isMatchingField(fields[i]))
 195.433 +                    matches.push(fields[i]);
 195.434 +            };
 195.435 +            return matches;
 195.436 +        },
 195.437 +
 195.438 +        parseJson: function (jsonString) {
 195.439 +            if (typeof jsonString == "string") {
 195.440 +                jsonString = ko.utils.stringTrim(jsonString);
 195.441 +                if (jsonString) {
 195.442 +                    if (window.JSON && window.JSON.parse) // Use native parsing where available
 195.443 +                        return window.JSON.parse(jsonString);
 195.444 +                    return (new Function("return " + jsonString))(); // Fallback on less safe parsing for older browsers
 195.445 +                }
 195.446 +            }
 195.447 +            return null;
 195.448 +        },
 195.449 +
 195.450 +        stringifyJson: function (data, replacer, space) {   // replacer and space are optional
 195.451 +            if ((typeof JSON == "undefined") || (typeof JSON.stringify == "undefined"))
 195.452 +                throw new Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js");
 195.453 +            return JSON.stringify(ko.utils.unwrapObservable(data), replacer, space);
 195.454 +        },
 195.455 +
 195.456 +        postJson: function (urlOrForm, data, options) {
 195.457 +            options = options || {};
 195.458 +            var params = options['params'] || {};
 195.459 +            var includeFields = options['includeFields'] || this.fieldsIncludedWithJsonPost;
 195.460 +            var url = urlOrForm;
 195.461 +
 195.462 +            // If we were given a form, use its 'action' URL and pick out any requested field values
 195.463 +            if((typeof urlOrForm == 'object') && (ko.utils.tagNameLower(urlOrForm) === "form")) {
 195.464 +                var originalForm = urlOrForm;
 195.465 +                url = originalForm.action;
 195.466 +                for (var i = includeFields.length - 1; i >= 0; i--) {
 195.467 +                    var fields = ko.utils.getFormFields(originalForm, includeFields[i]);
 195.468 +                    for (var j = fields.length - 1; j >= 0; j--)
 195.469 +                        params[fields[j].name] = fields[j].value;
 195.470 +                }
 195.471 +            }
 195.472 +
 195.473 +            data = ko.utils.unwrapObservable(data);
 195.474 +            var form = document.createElement("form");
 195.475 +            form.style.display = "none";
 195.476 +            form.action = url;
 195.477 +            form.method = "post";
 195.478 +            for (var key in data) {
 195.479 +                var input = document.createElement("input");
 195.480 +                input.name = key;
 195.481 +                input.value = ko.utils.stringifyJson(ko.utils.unwrapObservable(data[key]));
 195.482 +                form.appendChild(input);
 195.483 +            }
 195.484 +            for (var key in params) {
 195.485 +                var input = document.createElement("input");
 195.486 +                input.name = key;
 195.487 +                input.value = params[key];
 195.488 +                form.appendChild(input);
 195.489 +            }
 195.490 +            document.body.appendChild(form);
 195.491 +            options['submitter'] ? options['submitter'](form) : form.submit();
 195.492 +            setTimeout(function () { form.parentNode.removeChild(form); }, 0);
 195.493 +        }
 195.494 +    }
 195.495 +})();
 195.496 +
 195.497 +ko.exportSymbol('utils', ko.utils);
 195.498 +ko.exportSymbol('utils.arrayForEach', ko.utils.arrayForEach);
 195.499 +ko.exportSymbol('utils.arrayFirst', ko.utils.arrayFirst);
 195.500 +ko.exportSymbol('utils.arrayFilter', ko.utils.arrayFilter);
 195.501 +ko.exportSymbol('utils.arrayGetDistinctValues', ko.utils.arrayGetDistinctValues);
 195.502 +ko.exportSymbol('utils.arrayIndexOf', ko.utils.arrayIndexOf);
 195.503 +ko.exportSymbol('utils.arrayMap', ko.utils.arrayMap);
 195.504 +ko.exportSymbol('utils.arrayPushAll', ko.utils.arrayPushAll);
 195.505 +ko.exportSymbol('utils.arrayRemoveItem', ko.utils.arrayRemoveItem);
 195.506 +ko.exportSymbol('utils.extend', ko.utils.extend);
 195.507 +ko.exportSymbol('utils.fieldsIncludedWithJsonPost', ko.utils.fieldsIncludedWithJsonPost);
 195.508 +ko.exportSymbol('utils.getFormFields', ko.utils.getFormFields);
 195.509 +ko.exportSymbol('utils.peekObservable', ko.utils.peekObservable);
 195.510 +ko.exportSymbol('utils.postJson', ko.utils.postJson);
 195.511 +ko.exportSymbol('utils.parseJson', ko.utils.parseJson);
 195.512 +ko.exportSymbol('utils.registerEventHandler', ko.utils.registerEventHandler);
 195.513 +ko.exportSymbol('utils.stringifyJson', ko.utils.stringifyJson);
 195.514 +ko.exportSymbol('utils.range', ko.utils.range);
 195.515 +ko.exportSymbol('utils.toggleDomNodeCssClass', ko.utils.toggleDomNodeCssClass);
 195.516 +ko.exportSymbol('utils.triggerEvent', ko.utils.triggerEvent);
 195.517 +ko.exportSymbol('utils.unwrapObservable', ko.utils.unwrapObservable);
 195.518 +
 195.519 +if (!Function.prototype['bind']) {
 195.520 +    // Function.prototype.bind is a standard part of ECMAScript 5th Edition (December 2009, http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf)
 195.521 +    // In case the browser doesn't implement it natively, provide a JavaScript implementation. This implementation is based on the one in prototype.js
 195.522 +    Function.prototype['bind'] = function (object) {
 195.523 +        var originalFunction = this, args = Array.prototype.slice.call(arguments), object = args.shift();
 195.524 +        return function () {
 195.525 +            return originalFunction.apply(object, args.concat(Array.prototype.slice.call(arguments)));
 195.526 +        };
 195.527 +    };
 195.528 +}
 195.529 +
 195.530 +ko.utils.domData = new (function () {
 195.531 +    var uniqueId = 0;
 195.532 +    var dataStoreKeyExpandoPropertyName = "__ko__" + (new Date).getTime();
 195.533 +    var dataStore = {};
 195.534 +    return {
 195.535 +        get: function (node, key) {
 195.536 +            var allDataForNode = ko.utils.domData.getAll(node, false);
 195.537 +            return allDataForNode === undefined ? undefined : allDataForNode[key];
 195.538 +        },
 195.539 +        set: function (node, key, value) {
 195.540 +            if (value === undefined) {
 195.541 +                // Make sure we don't actually create a new domData key if we are actually deleting a value
 195.542 +                if (ko.utils.domData.getAll(node, false) === undefined)
 195.543 +                    return;
 195.544 +            }
 195.545 +            var allDataForNode = ko.utils.domData.getAll(node, true);
 195.546 +            allDataForNode[key] = value;
 195.547 +        },
 195.548 +        getAll: function (node, createIfNotFound) {
 195.549 +            var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
 195.550 +            var hasExistingDataStore = dataStoreKey && (dataStoreKey !== "null") && dataStore[dataStoreKey];
 195.551 +            if (!hasExistingDataStore) {
 195.552 +                if (!createIfNotFound)
 195.553 +                    return undefined;
 195.554 +                dataStoreKey = node[dataStoreKeyExpandoPropertyName] = "ko" + uniqueId++;
 195.555 +                dataStore[dataStoreKey] = {};
 195.556 +            }
 195.557 +            return dataStore[dataStoreKey];
 195.558 +        },
 195.559 +        clear: function (node) {
 195.560 +            var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
 195.561 +            if (dataStoreKey) {
 195.562 +                delete dataStore[dataStoreKey];
 195.563 +                node[dataStoreKeyExpandoPropertyName] = null;
 195.564 +                return true; // Exposing "did clean" flag purely so specs can infer whether things have been cleaned up as intended
 195.565 +            }
 195.566 +            return false;
 195.567 +        }
 195.568 +    }
 195.569 +})();
 195.570 +
 195.571 +ko.exportSymbol('utils.domData', ko.utils.domData);
 195.572 +ko.exportSymbol('utils.domData.clear', ko.utils.domData.clear); // Exporting only so specs can clear up after themselves fully
 195.573 +
 195.574 +ko.utils.domNodeDisposal = new (function () {
 195.575 +    var domDataKey = "__ko_domNodeDisposal__" + (new Date).getTime();
 195.576 +    var cleanableNodeTypes = { 1: true, 8: true, 9: true };       // Element, Comment, Document
 195.577 +    var cleanableNodeTypesWithDescendants = { 1: true, 9: true }; // Element, Document
 195.578 +
 195.579 +    function getDisposeCallbacksCollection(node, createIfNotFound) {
 195.580 +        var allDisposeCallbacks = ko.utils.domData.get(node, domDataKey);
 195.581 +        if ((allDisposeCallbacks === undefined) && createIfNotFound) {
 195.582 +            allDisposeCallbacks = [];
 195.583 +            ko.utils.domData.set(node, domDataKey, allDisposeCallbacks);
 195.584 +        }
 195.585 +        return allDisposeCallbacks;
 195.586 +    }
 195.587 +    function destroyCallbacksCollection(node) {
 195.588 +        ko.utils.domData.set(node, domDataKey, undefined);
 195.589 +    }
 195.590 +
 195.591 +    function cleanSingleNode(node) {
 195.592 +        // Run all the dispose callbacks
 195.593 +        var callbacks = getDisposeCallbacksCollection(node, false);
 195.594 +        if (callbacks) {
 195.595 +            callbacks = callbacks.slice(0); // Clone, as the array may be modified during iteration (typically, callbacks will remove themselves)
 195.596 +            for (var i = 0; i < callbacks.length; i++)
 195.597 +                callbacks[i](node);
 195.598 +        }
 195.599 +
 195.600 +        // Also erase the DOM data
 195.601 +        ko.utils.domData.clear(node);
 195.602 +
 195.603 +        // Special support for jQuery here because it's so commonly used.
 195.604 +        // Many jQuery plugins (including jquery.tmpl) store data using jQuery's equivalent of domData
 195.605 +        // so notify it to tear down any resources associated with the node & descendants here.
 195.606 +        if ((typeof jQuery == "function") && (typeof jQuery['cleanData'] == "function"))
 195.607 +            jQuery['cleanData']([node]);
 195.608 +
 195.609 +        // Also clear any immediate-child comment nodes, as these wouldn't have been found by
 195.610 +        // node.getElementsByTagName("*") in cleanNode() (comment nodes aren't elements)
 195.611 +        if (cleanableNodeTypesWithDescendants[node.nodeType])
 195.612 +            cleanImmediateCommentTypeChildren(node);
 195.613 +    }
 195.614 +
 195.615 +    function cleanImmediateCommentTypeChildren(nodeWithChildren) {
 195.616 +        var child, nextChild = nodeWithChildren.firstChild;
 195.617 +        while (child = nextChild) {
 195.618 +            nextChild = child.nextSibling;
 195.619 +            if (child.nodeType === 8)
 195.620 +                cleanSingleNode(child);
 195.621 +        }
 195.622 +    }
 195.623 +
 195.624 +    return {
 195.625 +        addDisposeCallback : function(node, callback) {
 195.626 +            if (typeof callback != "function")
 195.627 +                throw new Error("Callback must be a function");
 195.628 +            getDisposeCallbacksCollection(node, true).push(callback);
 195.629 +        },
 195.630 +
 195.631 +        removeDisposeCallback : function(node, callback) {
 195.632 +            var callbacksCollection = getDisposeCallbacksCollection(node, false);
 195.633 +            if (callbacksCollection) {
 195.634 +                ko.utils.arrayRemoveItem(callbacksCollection, callback);
 195.635 +                if (callbacksCollection.length == 0)
 195.636 +                    destroyCallbacksCollection(node);
 195.637 +            }
 195.638 +        },
 195.639 +
 195.640 +        cleanNode : function(node) {
 195.641 +            // First clean this node, where applicable
 195.642 +            if (cleanableNodeTypes[node.nodeType]) {
 195.643 +                cleanSingleNode(node);
 195.644 +
 195.645 +                // ... then its descendants, where applicable
 195.646 +                if (cleanableNodeTypesWithDescendants[node.nodeType]) {
 195.647 +                    // Clone the descendants list in case it changes during iteration
 195.648 +                    var descendants = [];
 195.649 +                    ko.utils.arrayPushAll(descendants, node.getElementsByTagName("*"));
 195.650 +                    for (var i = 0, j = descendants.length; i < j; i++)
 195.651 +                        cleanSingleNode(descendants[i]);
 195.652 +                }
 195.653 +            }
 195.654 +            return node;
 195.655 +        },
 195.656 +
 195.657 +        removeNode : function(node) {
 195.658 +            ko.cleanNode(node);
 195.659 +            if (node.parentNode)
 195.660 +                node.parentNode.removeChild(node);
 195.661 +        }
 195.662 +    }
 195.663 +})();
 195.664 +ko.cleanNode = ko.utils.domNodeDisposal.cleanNode; // Shorthand name for convenience
 195.665 +ko.removeNode = ko.utils.domNodeDisposal.removeNode; // Shorthand name for convenience
 195.666 +ko.exportSymbol('cleanNode', ko.cleanNode);
 195.667 +ko.exportSymbol('removeNode', ko.removeNode);
 195.668 +ko.exportSymbol('utils.domNodeDisposal', ko.utils.domNodeDisposal);
 195.669 +ko.exportSymbol('utils.domNodeDisposal.addDisposeCallback', ko.utils.domNodeDisposal.addDisposeCallback);
 195.670 +ko.exportSymbol('utils.domNodeDisposal.removeDisposeCallback', ko.utils.domNodeDisposal.removeDisposeCallback);
 195.671 +(function () {
 195.672 +    var leadingCommentRegex = /^(\s*)<!--(.*?)-->/;
 195.673 +
 195.674 +    function simpleHtmlParse(html) {
 195.675 +        // Based on jQuery's "clean" function, but only accounting for table-related elements.
 195.676 +        // If you have referenced jQuery, this won't be used anyway - KO will use jQuery's "clean" function directly
 195.677 +
 195.678 +        // Note that there's still an issue in IE < 9 whereby it will discard comment nodes that are the first child of
 195.679 +        // a descendant node. For example: "<div><!-- mycomment -->abc</div>" will get parsed as "<div>abc</div>"
 195.680 +        // This won't affect anyone who has referenced jQuery, and there's always the workaround of inserting a dummy node
 195.681 +        // (possibly a text node) in front of the comment. So, KO does not attempt to workaround this IE issue automatically at present.
 195.682 +
 195.683 +        // Trim whitespace, otherwise indexOf won't work as expected
 195.684 +        var tags = ko.utils.stringTrim(html).toLowerCase(), div = document.createElement("div");
 195.685 +
 195.686 +        // Finds the first match from the left column, and returns the corresponding "wrap" data from the right column
 195.687 +        var wrap = tags.match(/^<(thead|tbody|tfoot)/)              && [1, "<table>", "</table>"] ||
 195.688 +                   !tags.indexOf("<tr")                             && [2, "<table><tbody>", "</tbody></table>"] ||
 195.689 +                   (!tags.indexOf("<td") || !tags.indexOf("<th"))   && [3, "<table><tbody><tr>", "</tr></tbody></table>"] ||
 195.690 +                   /* anything else */                                 [0, "", ""];
 195.691 +
 195.692 +        // Go to html and back, then peel off extra wrappers
 195.693 +        // Note that we always prefix with some dummy text, because otherwise, IE<9 will strip out leading comment nodes in descendants. Total madness.
 195.694 +        var markup = "ignored<div>" + wrap[1] + html + wrap[2] + "</div>";
 195.695 +        if (typeof window['innerShiv'] == "function") {
 195.696 +            div.appendChild(window['innerShiv'](markup));
 195.697 +        } else {
 195.698 +            div.innerHTML = markup;
 195.699 +        }
 195.700 +
 195.701 +        // Move to the right depth
 195.702 +        while (wrap[0]--)
 195.703 +            div = div.lastChild;
 195.704 +
 195.705 +        return ko.utils.makeArray(div.lastChild.childNodes);
 195.706 +    }
 195.707 +
 195.708 +    function jQueryHtmlParse(html) {
 195.709 +        // jQuery's "parseHTML" function was introduced in jQuery 1.8.0 and is a documented public API.
 195.710 +        if (jQuery['parseHTML']) {
 195.711 +            return jQuery['parseHTML'](html);
 195.712 +        } else {
 195.713 +            // For jQuery < 1.8.0, we fall back on the undocumented internal "clean" function.
 195.714 +            var elems = jQuery['clean']([html]);
 195.715 +
 195.716 +            // As of jQuery 1.7.1, jQuery parses the HTML by appending it to some dummy parent nodes held in an in-memory document fragment.
 195.717 +            // Unfortunately, it never clears the dummy parent nodes from the document fragment, so it leaks memory over time.
 195.718 +            // Fix this by finding the top-most dummy parent element, and detaching it from its owner fragment.
 195.719 +            if (elems && elems[0]) {
 195.720 +                // Find the top-most parent element that's a direct child of a document fragment
 195.721 +                var elem = elems[0];
 195.722 +                while (elem.parentNode && elem.parentNode.nodeType !== 11 /* i.e., DocumentFragment */)
 195.723 +                    elem = elem.parentNode;
 195.724 +                // ... then detach it
 195.725 +                if (elem.parentNode)
 195.726 +                    elem.parentNode.removeChild(elem);
 195.727 +            }
 195.728 +
 195.729 +            return elems;
 195.730 +        }
 195.731 +    }
 195.732 +
 195.733 +    ko.utils.parseHtmlFragment = function(html) {
 195.734 +        return typeof jQuery != 'undefined' ? jQueryHtmlParse(html)   // As below, benefit from jQuery's optimisations where possible
 195.735 +                                            : simpleHtmlParse(html);  // ... otherwise, this simple logic will do in most common cases.
 195.736 +    };
 195.737 +
 195.738 +    ko.utils.setHtml = function(node, html) {
 195.739 +        ko.utils.emptyDomNode(node);
 195.740 +
 195.741 +        // There's no legitimate reason to display a stringified observable without unwrapping it, so we'll unwrap it
 195.742 +        html = ko.utils.unwrapObservable(html);
 195.743 +
 195.744 +        if ((html !== null) && (html !== undefined)) {
 195.745 +            if (typeof html != 'string')
 195.746 +                html = html.toString();
 195.747 +
 195.748 +            // jQuery contains a lot of sophisticated code to parse arbitrary HTML fragments,
 195.749 +            // for example <tr> elements which are not normally allowed to exist on their own.
 195.750 +            // If you've referenced jQuery we'll use that rather than duplicating its code.
 195.751 +            if (typeof jQuery != 'undefined') {
 195.752 +                jQuery(node)['html'](html);
 195.753 +            } else {
 195.754 +                // ... otherwise, use KO's own parsing logic.
 195.755 +                var parsedNodes = ko.utils.parseHtmlFragment(html);
 195.756 +                for (var i = 0; i < parsedNodes.length; i++)
 195.757 +                    node.appendChild(parsedNodes[i]);
 195.758 +            }
 195.759 +        }
 195.760 +    };
 195.761 +})();
 195.762 +
 195.763 +ko.exportSymbol('utils.parseHtmlFragment', ko.utils.parseHtmlFragment);
 195.764 +ko.exportSymbol('utils.setHtml', ko.utils.setHtml);
 195.765 +
 195.766 +ko.memoization = (function () {
 195.767 +    var memos = {};
 195.768 +
 195.769 +    function randomMax8HexChars() {
 195.770 +        return (((1 + Math.random()) * 0x100000000) | 0).toString(16).substring(1);
 195.771 +    }
 195.772 +    function generateRandomId() {
 195.773 +        return randomMax8HexChars() + randomMax8HexChars();
 195.774 +    }
 195.775 +    function findMemoNodes(rootNode, appendToArray) {
 195.776 +        if (!rootNode)
 195.777 +            return;
 195.778 +        if (rootNode.nodeType == 8) {
 195.779 +            var memoId = ko.memoization.parseMemoText(rootNode.nodeValue);
 195.780 +            if (memoId != null)
 195.781 +                appendToArray.push({ domNode: rootNode, memoId: memoId });
 195.782 +        } else if (rootNode.nodeType == 1) {
 195.783 +            for (var i = 0, childNodes = rootNode.childNodes, j = childNodes.length; i < j; i++)
 195.784 +                findMemoNodes(childNodes[i], appendToArray);
 195.785 +        }
 195.786 +    }
 195.787 +
 195.788 +    return {
 195.789 +        memoize: function (callback) {
 195.790 +            if (typeof callback != "function")
 195.791 +                throw new Error("You can only pass a function to ko.memoization.memoize()");
 195.792 +            var memoId = generateRandomId();
 195.793 +            memos[memoId] = callback;
 195.794 +            return "<!--[ko_memo:" + memoId + "]-->";
 195.795 +        },
 195.796 +
 195.797 +        unmemoize: function (memoId, callbackParams) {
 195.798 +            var callback = memos[memoId];
 195.799 +            if (callback === undefined)
 195.800 +                throw new Error("Couldn't find any memo with ID " + memoId + ". Perhaps it's already been unmemoized.");
 195.801 +            try {
 195.802 +                callback.apply(null, callbackParams || []);
 195.803 +                return true;
 195.804 +            }
 195.805 +            finally { delete memos[memoId]; }
 195.806 +        },
 195.807 +
 195.808 +        unmemoizeDomNodeAndDescendants: function (domNode, extraCallbackParamsArray) {
 195.809 +            var memos = [];
 195.810 +            findMemoNodes(domNode, memos);
 195.811 +            for (var i = 0, j = memos.length; i < j; i++) {
 195.812 +                var node = memos[i].domNode;
 195.813 +                var combinedParams = [node];
 195.814 +                if (extraCallbackParamsArray)
 195.815 +                    ko.utils.arrayPushAll(combinedParams, extraCallbackParamsArray);
 195.816 +                ko.memoization.unmemoize(memos[i].memoId, combinedParams);
 195.817 +                node.nodeValue = ""; // Neuter this node so we don't try to unmemoize it again
 195.818 +                if (node.parentNode)
 195.819 +                    node.parentNode.removeChild(node); // If possible, erase it totally (not always possible - someone else might just hold a reference to it then call unmemoizeDomNodeAndDescendants again)
 195.820 +            }
 195.821 +        },
 195.822 +
 195.823 +        parseMemoText: function (memoText) {
 195.824 +            var match = memoText.match(/^\[ko_memo\:(.*?)\]$/);
 195.825 +            return match ? match[1] : null;
 195.826 +        }
 195.827 +    };
 195.828 +})();
 195.829 +
 195.830 +ko.exportSymbol('memoization', ko.memoization);
 195.831 +ko.exportSymbol('memoization.memoize', ko.memoization.memoize);
 195.832 +ko.exportSymbol('memoization.unmemoize', ko.memoization.unmemoize);
 195.833 +ko.exportSymbol('memoization.parseMemoText', ko.memoization.parseMemoText);
 195.834 +ko.exportSymbol('memoization.unmemoizeDomNodeAndDescendants', ko.memoization.unmemoizeDomNodeAndDescendants);
 195.835 +ko.extenders = {
 195.836 +    'throttle': function(target, timeout) {
 195.837 +        // Throttling means two things:
 195.838 +
 195.839 +        // (1) For dependent observables, we throttle *evaluations* so that, no matter how fast its dependencies
 195.840 +        //     notify updates, the target doesn't re-evaluate (and hence doesn't notify) faster than a certain rate
 195.841 +        target['throttleEvaluation'] = timeout;
 195.842 +
 195.843 +        // (2) For writable targets (observables, or writable dependent observables), we throttle *writes*
 195.844 +        //     so the target cannot change value synchronously or faster than a certain rate
 195.845 +        var writeTimeoutInstance = null;
 195.846 +        return ko.dependentObservable({
 195.847 +            'read': target,
 195.848 +            'write': function(value) {
 195.849 +                clearTimeout(writeTimeoutInstance);
 195.850 +                writeTimeoutInstance = setTimeout(function() {
 195.851 +                    target(value);
 195.852 +                }, timeout);
 195.853 +            }
 195.854 +        });
 195.855 +    },
 195.856 +
 195.857 +    'notify': function(target, notifyWhen) {
 195.858 +        target["equalityComparer"] = notifyWhen == "always"
 195.859 +            ? function() { return false } // Treat all values as not equal
 195.860 +            : ko.observable["fn"]["equalityComparer"];
 195.861 +        return target;
 195.862 +    }
 195.863 +};
 195.864 +
 195.865 +function applyExtenders(requestedExtenders) {
 195.866 +    var target = this;
 195.867 +    if (requestedExtenders) {
 195.868 +        for (var key in requestedExtenders) {
 195.869 +            var extenderHandler = ko.extenders[key];
 195.870 +            if (typeof extenderHandler == 'function') {
 195.871 +                target = extenderHandler(target, requestedExtenders[key]);
 195.872 +            }
 195.873 +        }
 195.874 +    }
 195.875 +    return target;
 195.876 +}
 195.877 +
 195.878 +ko.exportSymbol('extenders', ko.extenders);
 195.879 +
 195.880 +ko.subscription = function (target, callback, disposeCallback) {
 195.881 +    this.target = target;
 195.882 +    this.callback = callback;
 195.883 +    this.disposeCallback = disposeCallback;
 195.884 +    ko.exportProperty(this, 'dispose', this.dispose);
 195.885 +};
 195.886 +ko.subscription.prototype.dispose = function () {
 195.887 +    this.isDisposed = true;
 195.888 +    this.disposeCallback();
 195.889 +};
 195.890 +
 195.891 +ko.subscribable = function () {
 195.892 +    this._subscriptions = {};
 195.893 +
 195.894 +    ko.utils.extend(this, ko.subscribable['fn']);
 195.895 +    ko.exportProperty(this, 'subscribe', this.subscribe);
 195.896 +    ko.exportProperty(this, 'extend', this.extend);
 195.897 +    ko.exportProperty(this, 'getSubscriptionsCount', this.getSubscriptionsCount);
 195.898 +}
 195.899 +
 195.900 +var defaultEvent = "change";
 195.901 +
 195.902 +ko.subscribable['fn'] = {
 195.903 +    subscribe: function (callback, callbackTarget, event) {
 195.904 +        event = event || defaultEvent;
 195.905 +        var boundCallback = callbackTarget ? callback.bind(callbackTarget) : callback;
 195.906 +
 195.907 +        var subscription = new ko.subscription(this, boundCallback, function () {
 195.908 +            ko.utils.arrayRemoveItem(this._subscriptions[event], subscription);
 195.909 +        }.bind(this));
 195.910 +
 195.911 +        if (!this._subscriptions[event])
 195.912 +            this._subscriptions[event] = [];
 195.913 +        this._subscriptions[event].push(subscription);
 195.914 +        return subscription;
 195.915 +    },
 195.916 +
 195.917 +    "notifySubscribers": function (valueToNotify, event) {
 195.918 +        event = event || defaultEvent;
 195.919 +        if (this._subscriptions[event]) {
 195.920 +            ko.dependencyDetection.ignore(function() {
 195.921 +                ko.utils.arrayForEach(this._subscriptions[event].slice(0), function (subscription) {
 195.922 +                    // In case a subscription was disposed during the arrayForEach cycle, check
 195.923 +                    // for isDisposed on each subscription before invoking its callback
 195.924 +                    if (subscription && (subscription.isDisposed !== true))
 195.925 +                        subscription.callback(valueToNotify);
 195.926 +                });
 195.927 +            }, this);
 195.928 +        }
 195.929 +    },
 195.930 +
 195.931 +    getSubscriptionsCount: function () {
 195.932 +        var total = 0;
 195.933 +        for (var eventName in this._subscriptions) {
 195.934 +            if (this._subscriptions.hasOwnProperty(eventName))
 195.935 +                total += this._subscriptions[eventName].length;
 195.936 +        }
 195.937 +        return total;
 195.938 +    },
 195.939 +
 195.940 +    extend: applyExtenders
 195.941 +};
 195.942 +
 195.943 +
 195.944 +ko.isSubscribable = function (instance) {
 195.945 +    return typeof instance.subscribe == "function" && typeof instance["notifySubscribers"] == "function";
 195.946 +};
 195.947 +
 195.948 +ko.exportSymbol('subscribable', ko.subscribable);
 195.949 +ko.exportSymbol('isSubscribable', ko.isSubscribable);
 195.950 +
 195.951 +ko.dependencyDetection = (function () {
 195.952 +    var _frames = [];
 195.953 +
 195.954 +    return {
 195.955 +        begin: function (callback) {
 195.956 +            _frames.push({ callback: callback, distinctDependencies:[] });
 195.957 +        },
 195.958 +
 195.959 +        end: function () {
 195.960 +            _frames.pop();
 195.961 +        },
 195.962 +
 195.963 +        registerDependency: function (subscribable) {
 195.964 +            if (!ko.isSubscribable(subscribable))
 195.965 +                throw new Error("Only subscribable things can act as dependencies");
 195.966 +            if (_frames.length > 0) {
 195.967 +                var topFrame = _frames[_frames.length - 1];
 195.968 +                if (!topFrame || ko.utils.arrayIndexOf(topFrame.distinctDependencies, subscribable) >= 0)
 195.969 +                    return;
 195.970 +                topFrame.distinctDependencies.push(subscribable);
 195.971 +                topFrame.callback(subscribable);
 195.972 +            }
 195.973 +        },
 195.974 +
 195.975 +        ignore: function(callback, callbackTarget, callbackArgs) {
 195.976 +            try {
 195.977 +                _frames.push(null);
 195.978 +                return callback.apply(callbackTarget, callbackArgs || []);
 195.979 +            } finally {
 195.980 +                _frames.pop();
 195.981 +            }
 195.982 +        }
 195.983 +    };
 195.984 +})();
 195.985 +var primitiveTypes = { 'undefined':true, 'boolean':true, 'number':true, 'string':true };
 195.986 +
 195.987 +ko.observable = function (initialValue) {
 195.988 +    var _latestValue = initialValue;
 195.989 +
 195.990 +    function observable() {
 195.991 +        if (arguments.length > 0) {
 195.992 +            // Write
 195.993 +
 195.994 +            // Ignore writes if the value hasn't changed
 195.995 +            if ((!observable['equalityComparer']) || !observable['equalityComparer'](_latestValue, arguments[0])) {
 195.996 +                observable.valueWillMutate();
 195.997 +                _latestValue = arguments[0];
 195.998 +                if (DEBUG) observable._latestValue = _latestValue;
 195.999 +                observable.valueHasMutated();
195.1000 +            }
195.1001 +            return this; // Permits chained assignments
195.1002 +        }
195.1003 +        else {
195.1004 +            // Read
195.1005 +            ko.dependencyDetection.registerDependency(observable); // The caller only needs to be notified of changes if they did a "read" operation
195.1006 +            return _latestValue;
195.1007 +        }
195.1008 +    }
195.1009 +    if (DEBUG) observable._latestValue = _latestValue;
195.1010 +    ko.subscribable.call(observable);
195.1011 +    observable.peek = function() { return _latestValue };
195.1012 +    observable.valueHasMutated = function () { observable["notifySubscribers"](_latestValue); }
195.1013 +    observable.valueWillMutate = function () { observable["notifySubscribers"](_latestValue, "beforeChange"); }
195.1014 +    ko.utils.extend(observable, ko.observable['fn']);
195.1015 +
195.1016 +    ko.exportProperty(observable, 'peek', observable.peek);
195.1017 +    ko.exportProperty(observable, "valueHasMutated", observable.valueHasMutated);
195.1018 +    ko.exportProperty(observable, "valueWillMutate", observable.valueWillMutate);
195.1019 +
195.1020 +    return observable;
195.1021 +}
195.1022 +
195.1023 +ko.observable['fn'] = {
195.1024 +    "equalityComparer": function valuesArePrimitiveAndEqual(a, b) {
195.1025 +        var oldValueIsPrimitive = (a === null) || (typeof(a) in primitiveTypes);
195.1026 +        return oldValueIsPrimitive ? (a === b) : false;
195.1027 +    }
195.1028 +};
195.1029 +
195.1030 +var protoProperty = ko.observable.protoProperty = "__ko_proto__";
195.1031 +ko.observable['fn'][protoProperty] = ko.observable;
195.1032 +
195.1033 +ko.hasPrototype = function(instance, prototype) {
195.1034 +    if ((instance === null) || (instance === undefined) || (instance[protoProperty] === undefined)) return false;
195.1035 +    if (instance[protoProperty] === prototype) return true;
195.1036 +    return ko.hasPrototype(instance[protoProperty], prototype); // Walk the prototype chain
195.1037 +};
195.1038 +
195.1039 +ko.isObservable = function (instance) {
195.1040 +    return ko.hasPrototype(instance, ko.observable);
195.1041 +}
195.1042 +ko.isWriteableObservable = function (instance) {
195.1043 +    // Observable
195.1044 +    if ((typeof instance == "function") && instance[protoProperty] === ko.observable)
195.1045 +        return true;
195.1046 +    // Writeable dependent observable
195.1047 +    if ((typeof instance == "function") && (instance[protoProperty] === ko.dependentObservable) && (instance.hasWriteFunction))
195.1048 +        return true;
195.1049 +    // Anything else
195.1050 +    return false;
195.1051 +}
195.1052 +
195.1053 +
195.1054 +ko.exportSymbol('observable', ko.observable);
195.1055 +ko.exportSymbol('isObservable', ko.isObservable);
195.1056 +ko.exportSymbol('isWriteableObservable', ko.isWriteableObservable);
195.1057 +ko.observableArray = function (initialValues) {
195.1058 +    if (arguments.length == 0) {
195.1059 +        // Zero-parameter constructor initializes to empty array
195.1060 +        initialValues = [];
195.1061 +    }
195.1062 +    if ((initialValues !== null) && (initialValues !== undefined) && !('length' in initialValues))
195.1063 +        throw new Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");
195.1064 +
195.1065 +    var result = ko.observable(initialValues);
195.1066 +    ko.utils.extend(result, ko.observableArray['fn']);
195.1067 +    return result;
195.1068 +}
195.1069 +
195.1070 +ko.observableArray['fn'] = {
195.1071 +    'remove': function (valueOrPredicate) {
195.1072 +        var underlyingArray = this.peek();
195.1073 +        var removedValues = [];
195.1074 +        var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
195.1075 +        for (var i = 0; i < underlyingArray.length; i++) {
195.1076 +            var value = underlyingArray[i];
195.1077 +            if (predicate(value)) {
195.1078 +                if (removedValues.length === 0) {
195.1079 +                    this.valueWillMutate();
195.1080 +                }
195.1081 +                removedValues.push(value);
195.1082 +                underlyingArray.splice(i, 1);
195.1083 +                i--;
195.1084 +            }
195.1085 +        }
195.1086 +        if (removedValues.length) {
195.1087 +            this.valueHasMutated();
195.1088 +        }
195.1089 +        return removedValues;
195.1090 +    },
195.1091 +
195.1092 +    'removeAll': function (arrayOfValues) {
195.1093 +        // If you passed zero args, we remove everything
195.1094 +        if (arrayOfValues === undefined) {
195.1095 +            var underlyingArray = this.peek();
195.1096 +            var allValues = underlyingArray.slice(0);
195.1097 +            this.valueWillMutate();
195.1098 +            underlyingArray.splice(0, underlyingArray.length);
195.1099 +            this.valueHasMutated();
195.1100 +            return allValues;
195.1101 +        }
195.1102 +        // If you passed an arg, we interpret it as an array of entries to remove
195.1103 +        if (!arrayOfValues)
195.1104 +            return [];
195.1105 +        return this['remove'](function (value) {
195.1106 +            return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
195.1107 +        });
195.1108 +    },
195.1109 +
195.1110 +    'destroy': function (valueOrPredicate) {
195.1111 +        var underlyingArray = this.peek();
195.1112 +        var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
195.1113 +        this.valueWillMutate();
195.1114 +        for (var i = underlyingArray.length - 1; i >= 0; i--) {
195.1115 +            var value = underlyingArray[i];
195.1116 +            if (predicate(value))
195.1117 +                underlyingArray[i]["_destroy"] = true;
195.1118 +        }
195.1119 +        this.valueHasMutated();
195.1120 +    },
195.1121 +
195.1122 +    'destroyAll': function (arrayOfValues) {
195.1123 +        // If you passed zero args, we destroy everything
195.1124 +        if (arrayOfValues === undefined)
195.1125 +            return this['destroy'](function() { return true });
195.1126 +
195.1127 +        // If you passed an arg, we interpret it as an array of entries to destroy
195.1128 +        if (!arrayOfValues)
195.1129 +            return [];
195.1130 +        return this['destroy'](function (value) {
195.1131 +            return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
195.1132 +        });
195.1133 +    },
195.1134 +
195.1135 +    'indexOf': function (item) {
195.1136 +        var underlyingArray = this();
195.1137 +        return ko.utils.arrayIndexOf(underlyingArray, item);
195.1138 +    },
195.1139 +
195.1140 +    'replace': function(oldItem, newItem) {
195.1141 +        var index = this['indexOf'](oldItem);
195.1142 +        if (index >= 0) {
195.1143 +            this.valueWillMutate();
195.1144 +            this.peek()[index] = newItem;
195.1145 +            this.valueHasMutated();
195.1146 +        }
195.1147 +    }
195.1148 +}
195.1149 +
195.1150 +// Populate ko.observableArray.fn with read/write functions from native arrays
195.1151 +// Important: Do not add any additional functions here that may reasonably be used to *read* data from the array
195.1152 +// because we'll eval them without causing subscriptions, so ko.computed output could end up getting stale
195.1153 +ko.utils.arrayForEach(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function (methodName) {
195.1154 +    ko.observableArray['fn'][methodName] = function () {
195.1155 +        // Use "peek" to avoid creating a subscription in any computed that we're executing in the context of
195.1156 +        // (for consistency with mutating regular observables)
195.1157 +        var underlyingArray = this.peek();
195.1158 +        this.valueWillMutate();
195.1159 +        var methodCallResult = underlyingArray[methodName].apply(underlyingArray, arguments);
195.1160 +        this.valueHasMutated();
195.1161 +        return methodCallResult;
195.1162 +    };
195.1163 +});
195.1164 +
195.1165 +// Populate ko.observableArray.fn with read-only functions from native arrays
195.1166 +ko.utils.arrayForEach(["slice"], function (methodName) {
195.1167 +    ko.observableArray['fn'][methodName] = function () {
195.1168 +        var underlyingArray = this();
195.1169 +        return underlyingArray[methodName].apply(underlyingArray, arguments);
195.1170 +    };
195.1171 +});
195.1172 +
195.1173 +ko.exportSymbol('observableArray', ko.observableArray);
195.1174 +ko.dependentObservable = function (evaluatorFunctionOrOptions, evaluatorFunctionTarget, options) {
195.1175 +    var _latestValue,
195.1176 +        _hasBeenEvaluated = false,
195.1177 +        _isBeingEvaluated = false,
195.1178 +        readFunction = evaluatorFunctionOrOptions;
195.1179 +
195.1180 +    if (readFunction && typeof readFunction == "object") {
195.1181 +        // Single-parameter syntax - everything is on this "options" param
195.1182 +        options = readFunction;
195.1183 +        readFunction = options["read"];
195.1184 +    } else {
195.1185 +        // Multi-parameter syntax - construct the options according to the params passed
195.1186 +        options = options || {};
195.1187 +        if (!readFunction)
195.1188 +            readFunction = options["read"];
195.1189 +    }
195.1190 +    if (typeof readFunction != "function")
195.1191 +        throw new Error("Pass a function that returns the value of the ko.computed");
195.1192 +
195.1193 +    function addSubscriptionToDependency(subscribable) {
195.1194 +        _subscriptionsToDependencies.push(subscribable.subscribe(evaluatePossiblyAsync));
195.1195 +    }
195.1196 +
195.1197 +    function disposeAllSubscriptionsToDependencies() {
195.1198 +        ko.utils.arrayForEach(_subscriptionsToDependencies, function (subscription) {
195.1199 +            subscription.dispose();
195.1200 +        });
195.1201 +        _subscriptionsToDependencies = [];
195.1202 +    }
195.1203 +
195.1204 +    function evaluatePossiblyAsync() {
195.1205 +        var throttleEvaluationTimeout = dependentObservable['throttleEvaluation'];
195.1206 +        if (throttleEvaluationTimeout && throttleEvaluationTimeout >= 0) {
195.1207 +            clearTimeout(evaluationTimeoutInstance);
195.1208 +            evaluationTimeoutInstance = setTimeout(evaluateImmediate, throttleEvaluationTimeout);
195.1209 +        } else
195.1210 +            evaluateImmediate();
195.1211 +    }
195.1212 +
195.1213 +    function evaluateImmediate() {
195.1214 +        if (_isBeingEvaluated) {
195.1215 +            // If the evaluation of a ko.computed causes side effects, it's possible that it will trigger its own re-evaluation.
195.1216 +            // This is not desirable (it's hard for a developer to realise a chain of dependencies might cause this, and they almost
195.1217 +            // certainly didn't intend infinite re-evaluations). So, for predictability, we simply prevent ko.computeds from causing
195.1218 +            // their own re-evaluation. Further discussion at https://github.com/SteveSanderson/knockout/pull/387
195.1219 +            return;
195.1220 +        }
195.1221 +
195.1222 +        // Don't dispose on first evaluation, because the "disposeWhen" callback might
195.1223 +        // e.g., dispose when the associated DOM element isn't in the doc, and it's not
195.1224 +        // going to be in the doc until *after* the first evaluation
195.1225 +        if (_hasBeenEvaluated && disposeWhen()) {
195.1226 +            dispose();
195.1227 +            return;
195.1228 +        }
195.1229 +
195.1230 +        _isBeingEvaluated = true;
195.1231 +        try {
195.1232 +            // Initially, we assume that none of the subscriptions are still being used (i.e., all are candidates for disposal).
195.1233 +            // Then, during evaluation, we cross off any that are in fact still being used.
195.1234 +            var disposalCandidates = ko.utils.arrayMap(_subscriptionsToDependencies, function(item) {return item.target;});
195.1235 +
195.1236 +            ko.dependencyDetection.begin(function(subscribable) {
195.1237 +                var inOld;
195.1238 +                if ((inOld = ko.utils.arrayIndexOf(disposalCandidates, subscribable)) >= 0)
195.1239 +                    disposalCandidates[inOld] = undefined; // Don't want to dispose this subscription, as it's still being used
195.1240 +                else
195.1241 +                    addSubscriptionToDependency(subscribable); // Brand new subscription - add it
195.1242 +            });
195.1243 +
195.1244 +            var newValue = readFunction.call(evaluatorFunctionTarget);
195.1245 +
195.1246 +            // For each subscription no longer being used, remove it from the active subscriptions list and dispose it
195.1247 +            for (var i = disposalCandidates.length - 1; i >= 0; i--) {
195.1248 +                if (disposalCandidates[i])
195.1249 +                    _subscriptionsToDependencies.splice(i, 1)[0].dispose();
195.1250 +            }
195.1251 +            _hasBeenEvaluated = true;
195.1252 +
195.1253 +            dependentObservable["notifySubscribers"](_latestValue, "beforeChange");
195.1254 +            _latestValue = newValue;
195.1255 +            if (DEBUG) dependentObservable._latestValue = _latestValue;
195.1256 +        } finally {
195.1257 +            ko.dependencyDetection.end();
195.1258 +        }
195.1259 +
195.1260 +        dependentObservable["notifySubscribers"](_latestValue);
195.1261 +        _isBeingEvaluated = false;
195.1262 +        if (!_subscriptionsToDependencies.length)
195.1263 +            dispose();
195.1264 +    }
195.1265 +
195.1266 +    function dependentObservable() {
195.1267 +        if (arguments.length > 0) {
195.1268 +            if (typeof writeFunction === "function") {
195.1269 +                // Writing a value
195.1270 +                writeFunction.apply(evaluatorFunctionTarget, arguments);
195.1271 +            } else {
195.1272 +                throw new Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.");
195.1273 +            }
195.1274 +            return this; // Permits chained assignments
195.1275 +        } else {
195.1276 +            // Reading the value
195.1277 +            if (!_hasBeenEvaluated)
195.1278 +                evaluateImmediate();
195.1279 +            ko.dependencyDetection.registerDependency(dependentObservable);
195.1280 +            return _latestValue;
195.1281 +        }
195.1282 +    }
195.1283 +
195.1284 +    function peek() {
195.1285 +        if (!_hasBeenEvaluated)
195.1286 +            evaluateImmediate();
195.1287 +        return _latestValue;
195.1288 +    }
195.1289 +
195.1290 +    function isActive() {
195.1291 +        return !_hasBeenEvaluated || _subscriptionsToDependencies.length > 0;
195.1292 +    }
195.1293 +
195.1294 +    // By here, "options" is always non-null
195.1295 +    var writeFunction = options["write"],
195.1296 +        disposeWhenNodeIsRemoved = options["disposeWhenNodeIsRemoved"] || options.disposeWhenNodeIsRemoved || null,
195.1297 +        disposeWhen = options["disposeWhen"] || options.disposeWhen || function() { return false; },
195.1298 +        dispose = disposeAllSubscriptionsToDependencies,
195.1299 +        _subscriptionsToDependencies = [],
195.1300 +        evaluationTimeoutInstance = null;
195.1301 +
195.1302 +    if (!evaluatorFunctionTarget)
195.1303 +        evaluatorFunctionTarget = options["owner"];
195.1304 +
195.1305 +    dependentObservable.peek = peek;
195.1306 +    dependentObservable.getDependenciesCount = function () { return _subscriptionsToDependencies.length; };
195.1307 +    dependentObservable.hasWriteFunction = typeof options["write"] === "function";
195.1308 +    dependentObservable.dispose = function () { dispose(); };
195.1309 +    dependentObservable.isActive = isActive;
195.1310 +    dependentObservable.valueHasMutated = function() {
195.1311 +        _hasBeenEvaluated = false;
195.1312 +        evaluateImmediate();
195.1313 +    };
195.1314 +
195.1315 +    ko.subscribable.call(dependentObservable);
195.1316 +    ko.utils.extend(dependentObservable, ko.dependentObservable['fn']);
195.1317 +
195.1318 +    ko.exportProperty(dependentObservable, 'peek', dependentObservable.peek);
195.1319 +    ko.exportProperty(dependentObservable, 'dispose', dependentObservable.dispose);
195.1320 +    ko.exportProperty(dependentObservable, 'isActive', dependentObservable.isActive);
195.1321 +    ko.exportProperty(dependentObservable, 'getDependenciesCount', dependentObservable.getDependenciesCount);
195.1322 +
195.1323 +    // Evaluate, unless deferEvaluation is true
195.1324 +    if (options['deferEvaluation'] !== true)
195.1325 +        evaluateImmediate();
195.1326 +
195.1327 +    // Build "disposeWhenNodeIsRemoved" and "disposeWhenNodeIsRemovedCallback" option values.
195.1328 +    // But skip if isActive is false (there will never be any dependencies to dispose).
195.1329 +    // (Note: "disposeWhenNodeIsRemoved" option both proactively disposes as soon as the node is removed using ko.removeNode(),
195.1330 +    // plus adds a "disposeWhen" callback that, on each evaluation, disposes if the node was removed by some other means.)
195.1331 +    if (disposeWhenNodeIsRemoved && isActive()) {
195.1332 +        dispose = function() {
195.1333 +            ko.utils.domNodeDisposal.removeDisposeCallback(disposeWhenNodeIsRemoved, arguments.callee);
195.1334 +            disposeAllSubscriptionsToDependencies();
195.1335 +        };
195.1336 +        ko.utils.domNodeDisposal.addDisposeCallback(disposeWhenNodeIsRemoved, dispose);
195.1337 +        var existingDisposeWhenFunction = disposeWhen;
195.1338 +        disposeWhen = function () {
195.1339 +            return !ko.utils.domNodeIsAttachedToDocument(disposeWhenNodeIsRemoved) || existingDisposeWhenFunction();
195.1340 +        }
195.1341 +    }
195.1342 +
195.1343 +    return dependentObservable;
195.1344 +};
195.1345 +
195.1346 +ko.isComputed = function(instance) {
195.1347 +    return ko.hasPrototype(instance, ko.dependentObservable);
195.1348 +};
195.1349 +
195.1350 +var protoProp = ko.observable.protoProperty; // == "__ko_proto__"
195.1351 +ko.dependentObservable[protoProp] = ko.observable;
195.1352 +
195.1353 +ko.dependentObservable['fn'] = {};
195.1354 +ko.dependentObservable['fn'][protoProp] = ko.dependentObservable;
195.1355 +
195.1356 +ko.exportSymbol('dependentObservable', ko.dependentObservable);
195.1357 +ko.exportSymbol('computed', ko.dependentObservable); // Make "ko.computed" an alias for "ko.dependentObservable"
195.1358 +ko.exportSymbol('isComputed', ko.isComputed);
195.1359 +
195.1360 +(function() {
195.1361 +    var maxNestedObservableDepth = 10; // Escape the (unlikely) pathalogical case where an observable's current value is itself (or similar reference cycle)
195.1362 +
195.1363 +    ko.toJS = function(rootObject) {
195.1364 +        if (arguments.length == 0)
195.1365 +            throw new Error("When calling ko.toJS, pass the object you want to convert.");
195.1366 +
195.1367 +        // We just unwrap everything at every level in the object graph
195.1368 +        return mapJsObjectGraph(rootObject, function(valueToMap) {
195.1369 +            // Loop because an observable's value might in turn be another observable wrapper
195.1370 +            for (var i = 0; ko.isObservable(valueToMap) && (i < maxNestedObservableDepth); i++)
195.1371 +                valueToMap = valueToMap();
195.1372 +            return valueToMap;
195.1373 +        });
195.1374 +    };
195.1375 +
195.1376 +    ko.toJSON = function(rootObject, replacer, space) {     // replacer and space are optional
195.1377 +        var plainJavaScriptObject = ko.toJS(rootObject);
195.1378 +        return ko.utils.stringifyJson(plainJavaScriptObject, replacer, space);
195.1379 +    };
195.1380 +
195.1381 +    function mapJsObjectGraph(rootObject, mapInputCallback, visitedObjects) {
195.1382 +        visitedObjects = visitedObjects || new objectLookup();
195.1383 +
195.1384 +        rootObject = mapInputCallback(rootObject);
195.1385 +        var canHaveProperties = (typeof rootObject == "object") && (rootObject !== null) && (rootObject !== undefined) && (!(rootObject instanceof Date));
195.1386 +        if (!canHaveProperties)
195.1387 +            return rootObject;
195.1388 +
195.1389 +        var outputProperties = rootObject instanceof Array ? [] : {};
195.1390 +        visitedObjects.save(rootObject, outputProperties);
195.1391 +
195.1392 +        visitPropertiesOrArrayEntries(rootObject, function(indexer) {
195.1393 +            var propertyValue = mapInputCallback(rootObject[indexer]);
195.1394 +
195.1395 +            switch (typeof propertyValue) {
195.1396 +                case "boolean":
195.1397 +                case "number":
195.1398 +                case "string":
195.1399 +                case "function":
195.1400 +                    outputProperties[indexer] = propertyValue;
195.1401 +                    break;
195.1402 +                case "object":
195.1403 +                case "undefined":
195.1404 +                    var previouslyMappedValue = visitedObjects.get(propertyValue);
195.1405 +                    outputProperties[indexer] = (previouslyMappedValue !== undefined)
195.1406 +                        ? previouslyMappedValue
195.1407 +                        : mapJsObjectGraph(propertyValue, mapInputCallback, visitedObjects);
195.1408 +                    break;
195.1409 +            }
195.1410 +        });
195.1411 +
195.1412 +        return outputProperties;
195.1413 +    }
195.1414 +
195.1415 +    function visitPropertiesOrArrayEntries(rootObject, visitorCallback) {
195.1416 +        if (rootObject instanceof Array) {
195.1417 +            for (var i = 0; i < rootObject.length; i++)
195.1418 +                visitorCallback(i);
195.1419 +
195.1420 +            // For arrays, also respect toJSON property for custom mappings (fixes #278)
195.1421 +            if (typeof rootObject['toJSON'] == 'function')
195.1422 +                visitorCallback('toJSON');
195.1423 +        } else {
195.1424 +            for (var propertyName in rootObject)
195.1425 +                visitorCallback(propertyName);
195.1426 +        }
195.1427 +    };
195.1428 +
195.1429 +    function objectLookup() {
195.1430 +        var keys = [];
195.1431 +        var values = [];
195.1432 +        this.save = function(key, value) {
195.1433 +            var existingIndex = ko.utils.arrayIndexOf(keys, key);
195.1434 +            if (existingIndex >= 0)
195.1435 +                values[existingIndex] = value;
195.1436 +            else {
195.1437 +                keys.push(key);
195.1438 +                values.push(value);
195.1439 +            }
195.1440 +        };
195.1441 +        this.get = function(key) {
195.1442 +            var existingIndex = ko.utils.arrayIndexOf(keys, key);
195.1443 +            return (existingIndex >= 0) ? values[existingIndex] : undefined;
195.1444 +        };
195.1445 +    };
195.1446 +})();
195.1447 +
195.1448 +ko.exportSymbol('toJS', ko.toJS);
195.1449 +ko.exportSymbol('toJSON', ko.toJSON);
195.1450 +(function () {
195.1451 +    var hasDomDataExpandoProperty = '__ko__hasDomDataOptionValue__';
195.1452 +
195.1453 +    // Normally, SELECT elements and their OPTIONs can only take value of type 'string' (because the values
195.1454 +    // are stored on DOM attributes). ko.selectExtensions provides a way for SELECTs/OPTIONs to have values
195.1455 +    // that are arbitrary objects. This is very convenient when implementing things like cascading dropdowns.
195.1456 +    ko.selectExtensions = {
195.1457 +        readValue : function(element) {
195.1458 +            switch (ko.utils.tagNameLower(element)) {
195.1459 +                case 'option':
195.1460 +                    if (element[hasDomDataExpandoProperty] === true)
195.1461 +                        return ko.utils.domData.get(element, ko.bindingHandlers.options.optionValueDomDataKey);
195.1462 +                    return ko.utils.ieVersion <= 7
195.1463 +                        ? (element.getAttributeNode('value').specified ? element.value : element.text)
195.1464 +                        : element.value;
195.1465 +                case 'select':
195.1466 +                    return element.selectedIndex >= 0 ? ko.selectExtensions.readValue(element.options[element.selectedIndex]) : undefined;
195.1467 +                default:
195.1468 +                    return element.value;
195.1469 +            }
195.1470 +        },
195.1471 +
195.1472 +        writeValue: function(element, value) {
195.1473 +            switch (ko.utils.tagNameLower(element)) {
195.1474 +                case 'option':
195.1475 +                    switch(typeof value) {
195.1476 +                        case "string":
195.1477 +                            ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, undefined);
195.1478 +                            if (hasDomDataExpandoProperty in element) { // IE <= 8 throws errors if you delete non-existent properties from a DOM node
195.1479 +                                delete element[hasDomDataExpandoProperty];
195.1480 +                            }
195.1481 +                            element.value = value;
195.1482 +                            break;
195.1483 +                        default:
195.1484 +                            // Store arbitrary object using DomData
195.1485 +                            ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, value);
195.1486 +                            element[hasDomDataExpandoProperty] = true;
195.1487 +
195.1488 +                            // Special treatment of numbers is just for backward compatibility. KO 1.2.1 wrote numerical values to element.value.
195.1489 +                            element.value = typeof value === "number" ? value : "";
195.1490 +                            break;
195.1491 +                    }
195.1492 +                    break;
195.1493 +                case 'select':
195.1494 +                    for (var i = element.options.length - 1; i >= 0; i--) {
195.1495 +                        if (ko.selectExtensions.readValue(element.options[i]) == value) {
195.1496 +                            element.selectedIndex = i;
195.1497 +                            break;
195.1498 +                        }
195.1499 +                    }
195.1500 +                    break;
195.1501 +                default:
195.1502 +                    if ((value === null) || (value === undefined))
195.1503 +                        value = "";
195.1504 +                    element.value = value;
195.1505 +                    break;
195.1506 +            }
195.1507 +        }
195.1508 +    };
195.1509 +})();
195.1510 +
195.1511 +ko.exportSymbol('selectExtensions', ko.selectExtensions);
195.1512 +ko.exportSymbol('selectExtensions.readValue', ko.selectExtensions.readValue);
195.1513 +ko.exportSymbol('selectExtensions.writeValue', ko.selectExtensions.writeValue);
195.1514 +ko.expressionRewriting = (function () {
195.1515 +    var restoreCapturedTokensRegex = /\@ko_token_(\d+)\@/g;
195.1516 +    var javaScriptReservedWords = ["true", "false"];
195.1517 +
195.1518 +    // Matches something that can be assigned to--either an isolated identifier or something ending with a property accessor
195.1519 +    // This is designed to be simple and avoid false negatives, but could produce false positives (e.g., a+b.c).
195.1520 +    var javaScriptAssignmentTarget = /^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i;
195.1521 +
195.1522 +    function restoreTokens(string, tokens) {
195.1523 +        var prevValue = null;
195.1524 +        while (string != prevValue) { // Keep restoring tokens until it no longer makes a difference (they may be nested)
195.1525 +            prevValue = string;
195.1526 +            string = string.replace(restoreCapturedTokensRegex, function (match, tokenIndex) {
195.1527 +                return tokens[tokenIndex];
195.1528 +            });
195.1529 +        }
195.1530 +        return string;
195.1531 +    }
195.1532 +
195.1533 +    function getWriteableValue(expression) {
195.1534 +        if (ko.utils.arrayIndexOf(javaScriptReservedWords, ko.utils.stringTrim(expression).toLowerCase()) >= 0)
195.1535 +            return false;
195.1536 +        var match = expression.match(javaScriptAssignmentTarget);
195.1537 +        return match === null ? false : match[1] ? ('Object(' + match[1] + ')' + match[2]) : expression;
195.1538 +    }
195.1539 +
195.1540 +    function ensureQuoted(key) {
195.1541 +        var trimmedKey = ko.utils.stringTrim(key);
195.1542 +        switch (trimmedKey.length && trimmedKey.charAt(0)) {
195.1543 +            case "'":
195.1544 +            case '"':
195.1545 +                return key;
195.1546 +            default:
195.1547 +                return "'" + trimmedKey + "'";
195.1548 +        }
195.1549 +    }
195.1550 +
195.1551 +    return {
195.1552 +        bindingRewriteValidators: [],
195.1553 +
195.1554 +        parseObjectLiteral: function(objectLiteralString) {
195.1555 +            // A full tokeniser+lexer would add too much weight to this library, so here's a simple parser
195.1556 +            // that is sufficient just to split an object literal string into a set of top-level key-value pairs
195.1557 +
195.1558 +            var str = ko.utils.stringTrim(objectLiteralString);
195.1559 +            if (str.length < 3)
195.1560 +                return [];
195.1561 +            if (str.charAt(0) === "{")// Ignore any braces surrounding the whole object literal
195.1562 +                str = str.substring(1, str.length - 1);
195.1563 +
195.1564 +            // Pull out any string literals and regex literals
195.1565 +            var tokens = [];
195.1566 +            var tokenStart = null, tokenEndChar;
195.1567 +            for (var position = 0; position < str.length; position++) {
195.1568 +                var c = str.charAt(position);
195.1569 +                if (tokenStart === null) {
195.1570 +                    switch (c) {
195.1571 +                        case '"':
195.1572 +                        case "'":
195.1573 +                        case "/":
195.1574 +                            tokenStart = position;
195.1575 +                            tokenEndChar = c;
195.1576 +                            break;
195.1577 +                    }
195.1578 +                } else if ((c == tokenEndChar) && (str.charAt(position - 1) !== "\\")) {
195.1579 +                    var token = str.substring(tokenStart, position + 1);
195.1580 +                    tokens.push(token);
195.1581 +                    var replacement = "@ko_token_" + (tokens.length - 1) + "@";
195.1582 +                    str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
195.1583 +                    position -= (token.length - replacement.length);
195.1584 +                    tokenStart = null;
195.1585 +                }
195.1586 +            }
195.1587 +
195.1588 +            // Next pull out balanced paren, brace, and bracket blocks
195.1589 +            tokenStart = null;
195.1590 +            tokenEndChar = null;
195.1591 +            var tokenDepth = 0, tokenStartChar = null;
195.1592 +            for (var position = 0; position < str.length; position++) {
195.1593 +                var c = str.charAt(position);
195.1594 +                if (tokenStart === null) {
195.1595 +                    switch (c) {
195.1596 +                        case "{": tokenStart = position; tokenStartChar = c;
195.1597 +                                  tokenEndChar = "}";
195.1598 +                                  break;
195.1599 +                        case "(": tokenStart = position; tokenStartChar = c;
195.1600 +                                  tokenEndChar = ")";
195.1601 +                                  break;
195.1602 +                        case "[": tokenStart = position; tokenStartChar = c;
195.1603 +                                  tokenEndChar = "]";
195.1604 +                                  break;
195.1605 +                    }
195.1606 +                }
195.1607 +
195.1608 +                if (c === tokenStartChar)
195.1609 +                    tokenDepth++;
195.1610 +                else if (c === tokenEndChar) {
195.1611 +                    tokenDepth--;
195.1612 +                    if (tokenDepth === 0) {
195.1613 +                        var token = str.substring(tokenStart, position + 1);
195.1614 +                        tokens.push(token);
195.1615 +                        var replacement = "@ko_token_" + (tokens.length - 1) + "@";
195.1616 +                        str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
195.1617 +                        position -= (token.length - replacement.length);
195.1618 +                        tokenStart = null;
195.1619 +                    }
195.1620 +                }
195.1621 +            }
195.1622 +
195.1623 +            // Now we can safely split on commas to get the key/value pairs
195.1624 +            var result = [];
195.1625 +            var keyValuePairs = str.split(",");
195.1626 +            for (var i = 0, j = keyValuePairs.length; i < j; i++) {
195.1627 +                var pair = keyValuePairs[i];
195.1628 +                var colonPos = pair.indexOf(":");
195.1629 +                if ((colonPos > 0) && (colonPos < pair.length - 1)) {
195.1630 +                    var key = pair.substring(0, colonPos);
195.1631 +                    var value = pair.substring(colonPos + 1);
195.1632 +                    result.push({ 'key': restoreTokens(key, tokens), 'value': restoreTokens(value, tokens) });
195.1633 +                } else {
195.1634 +                    result.push({ 'unknown': restoreTokens(pair, tokens) });
195.1635 +                }
195.1636 +            }
195.1637 +            return result;
195.1638 +        },
195.1639 +
195.1640 +        preProcessBindings: function (objectLiteralStringOrKeyValueArray) {
195.1641 +            var keyValueArray = typeof objectLiteralStringOrKeyValueArray === "string"
195.1642 +                ? ko.expressionRewriting.parseObjectLiteral(objectLiteralStringOrKeyValueArray)
195.1643 +                : objectLiteralStringOrKeyValueArray;
195.1644 +            var resultStrings = [], propertyAccessorResultStrings = [];
195.1645 +
195.1646 +            var keyValueEntry;
195.1647 +            for (var i = 0; keyValueEntry = keyValueArray[i]; i++) {
195.1648 +                if (resultStrings.length > 0)
195.1649 +                    resultStrings.push(",");
195.1650 +
195.1651 +                if (keyValueEntry['key']) {
195.1652 +                    var quotedKey = ensureQuoted(keyValueEntry['key']), val = keyValueEntry['value'];
195.1653 +                    resultStrings.push(quotedKey);
195.1654 +                    resultStrings.push(":");
195.1655 +                    resultStrings.push(val);
195.1656 +
195.1657 +                    if (val = getWriteableValue(ko.utils.stringTrim(val))) {
195.1658 +                        if (propertyAccessorResultStrings.length > 0)
195.1659 +                            propertyAccessorResultStrings.push(", ");
195.1660 +                        propertyAccessorResultStrings.push(quotedKey + " : function(__ko_value) { " + val + " = __ko_value; }");
195.1661 +                    }
195.1662 +                } else if (keyValueEntry['unknown']) {
195.1663 +                    resultStrings.push(keyValueEntry['unknown']);
195.1664 +                }
195.1665 +            }
195.1666 +
195.1667 +            var combinedResult = resultStrings.join("");
195.1668 +            if (propertyAccessorResultStrings.length > 0) {
195.1669 +                var allPropertyAccessors = propertyAccessorResultStrings.join("");
195.1670 +                combinedResult = combinedResult + ", '_ko_property_writers' : { " + allPropertyAccessors + " } ";
195.1671 +            }
195.1672 +
195.1673 +            return combinedResult;
195.1674 +        },
195.1675 +
195.1676 +        keyValueArrayContainsKey: function(keyValueArray, key) {
195.1677 +            for (var i = 0; i < keyValueArray.length; i++)
195.1678 +                if (ko.utils.stringTrim(keyValueArray[i]['key']) == key)
195.1679 +                    return true;
195.1680 +            return false;
195.1681 +        },
195.1682 +
195.1683 +        // Internal, private KO utility for updating model properties from within bindings
195.1684 +        // property:            If the property being updated is (or might be) an observable, pass it here
195.1685 +        //                      If it turns out to be a writable observable, it will be written to directly
195.1686 +        // allBindingsAccessor: All bindings in the current execution context.
195.1687 +        //                      This will be searched for a '_ko_property_writers' property in case you're writing to a non-observable
195.1688 +        // key:                 The key identifying the property to be written. Example: for { hasFocus: myValue }, write to 'myValue' by specifying the key 'hasFocus'
195.1689 +        // value:               The value to be written
195.1690 +        // checkIfDifferent:    If true, and if the property being written is a writable observable, the value will only be written if
195.1691 +        //                      it is !== existing value on that writable observable
195.1692 +        writeValueToProperty: function(property, allBindingsAccessor, key, value, checkIfDifferent) {
195.1693 +            if (!property || !ko.isWriteableObservable(property)) {
195.1694 +                var propWriters = allBindingsAccessor()['_ko_property_writers'];
195.1695 +                if (propWriters && propWriters[key])
195.1696 +                    propWriters[key](value);
195.1697 +            } else if (!checkIfDifferent || property.peek() !== value) {
195.1698 +                property(value);
195.1699 +            }
195.1700 +        }
195.1701 +    };
195.1702 +})();
195.1703 +
195.1704 +ko.exportSymbol('expressionRewriting', ko.expressionRewriting);
195.1705 +ko.exportSymbol('expressionRewriting.bindingRewriteValidators', ko.expressionRewriting.bindingRewriteValidators);
195.1706 +ko.exportSymbol('expressionRewriting.parseObjectLiteral', ko.expressionRewriting.parseObjectLiteral);
195.1707 +ko.exportSymbol('expressionRewriting.preProcessBindings', ko.expressionRewriting.preProcessBindings);
195.1708 +
195.1709 +// For backward compatibility, define the following aliases. (Previously, these function names were misleading because
195.1710 +// they referred to JSON specifically, even though they actually work with arbitrary JavaScript object literal expressions.)
195.1711 +ko.exportSymbol('jsonExpressionRewriting', ko.expressionRewriting);
195.1712 +ko.exportSymbol('jsonExpressionRewriting.insertPropertyAccessorsIntoJson', ko.expressionRewriting.preProcessBindings);(function() {
195.1713 +    // "Virtual elements" is an abstraction on top of the usual DOM API which understands the notion that comment nodes
195.1714 +    // may be used to represent hierarchy (in addition to the DOM's natural hierarchy).
195.1715 +    // If you call the DOM-manipulating functions on ko.virtualElements, you will be able to read and write the state
195.1716 +    // of that virtual hierarchy
195.1717 +    //
195.1718 +    // The point of all this is to support containerless templates (e.g., <!-- ko foreach:someCollection -->blah<!-- /ko -->)
195.1719 +    // without having to scatter special cases all over the binding and templating code.
195.1720 +
195.1721 +    // IE 9 cannot reliably read the "nodeValue" property of a comment node (see https://github.com/SteveSanderson/knockout/issues/186)
195.1722 +    // but it does give them a nonstandard alternative property called "text" that it can read reliably. Other browsers don't have that property.
195.1723 +    // So, use node.text where available, and node.nodeValue elsewhere
195.1724 +    var commentNodesHaveTextProperty = document.createComment("test").text === "<!--test-->";
195.1725 +
195.1726 +    var startCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*-->$/ : /^\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*$/;
195.1727 +    var endCommentRegex =   commentNodesHaveTextProperty ? /^<!--\s*\/ko\s*-->$/ : /^\s*\/ko\s*$/;
195.1728 +    var htmlTagsWithOptionallyClosingChildren = { 'ul': true, 'ol': true };
195.1729 +
195.1730 +    function isStartComment(node) {
195.1731 +        return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(startCommentRegex);
195.1732 +    }
195.1733 +
195.1734 +    function isEndComment(node) {
195.1735 +        return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(endCommentRegex);
195.1736 +    }
195.1737 +
195.1738 +    function getVirtualChildren(startComment, allowUnbalanced) {
195.1739 +        var currentNode = startComment;
195.1740 +        var depth = 1;
195.1741 +        var children = [];
195.1742 +        while (currentNode = currentNode.nextSibling) {
195.1743 +            if (isEndComment(currentNode)) {
195.1744 +                depth--;
195.1745 +                if (depth === 0)
195.1746 +                    return children;
195.1747 +            }
195.1748 +
195.1749 +            children.push(currentNode);
195.1750 +
195.1751 +            if (isStartComment(currentNode))
195.1752 +                depth++;
195.1753 +        }
195.1754 +        if (!allowUnbalanced)
195.1755 +            throw new Error("Cannot find closing comment tag to match: " + startComment.nodeValue);
195.1756 +        return null;
195.1757 +    }
195.1758 +
195.1759 +    function getMatchingEndComment(startComment, allowUnbalanced) {
195.1760 +        var allVirtualChildren = getVirtualChildren(startComment, allowUnbalanced);
195.1761 +        if (allVirtualChildren) {
195.1762 +            if (allVirtualChildren.length > 0)
195.1763 +                return allVirtualChildren[allVirtualChildren.length - 1].nextSibling;
195.1764 +            return startComment.nextSibling;
195.1765 +        } else
195.1766 +            return null; // Must have no matching end comment, and allowUnbalanced is true
195.1767 +    }
195.1768 +
195.1769 +    function getUnbalancedChildTags(node) {
195.1770 +        // e.g., from <div>OK</div><!-- ko blah --><span>Another</span>, returns: <!-- ko blah --><span>Another</span>
195.1771 +        //       from <div>OK</div><!-- /ko --><!-- /ko -->,             returns: <!-- /ko --><!-- /ko -->
195.1772 +        var childNode = node.firstChild, captureRemaining = null;
195.1773 +        if (childNode) {
195.1774 +            do {
195.1775 +                if (captureRemaining)                   // We already hit an unbalanced node and are now just scooping up all subsequent nodes
195.1776 +                    captureRemaining.push(childNode);
195.1777 +                else if (isStartComment(childNode)) {
195.1778 +                    var matchingEndComment = getMatchingEndComment(childNode, /* allowUnbalanced: */ true);
195.1779 +                    if (matchingEndComment)             // It's a balanced tag, so skip immediately to the end of this virtual set
195.1780 +                        childNode = matchingEndComment;
195.1781 +                    else
195.1782 +                        captureRemaining = [childNode]; // It's unbalanced, so start capturing from this point
195.1783 +                } else if (isEndComment(childNode)) {
195.1784 +                    captureRemaining = [childNode];     // It's unbalanced (if it wasn't, we'd have skipped over it already), so start capturing
195.1785 +                }
195.1786 +            } while (childNode = childNode.nextSibling);
195.1787 +        }
195.1788 +        return captureRemaining;
195.1789 +    }
195.1790 +
195.1791 +    ko.virtualElements = {
195.1792 +        allowedBindings: {},
195.1793 +
195.1794 +        childNodes: function(node) {
195.1795 +            return isStartComment(node) ? getVirtualChildren(node) : node.childNodes;
195.1796 +        },
195.1797 +
195.1798 +        emptyNode: function(node) {
195.1799 +            if (!isStartComment(node))
195.1800 +                ko.utils.emptyDomNode(node);
195.1801 +            else {
195.1802 +                var virtualChildren = ko.virtualElements.childNodes(node);
195.1803 +                for (var i = 0, j = virtualChildren.length; i < j; i++)
195.1804 +                    ko.removeNode(virtualChildren[i]);
195.1805 +            }
195.1806 +        },
195.1807 +
195.1808 +        setDomNodeChildren: function(node, childNodes) {
195.1809 +            if (!isStartComment(node))
195.1810 +                ko.utils.setDomNodeChildren(node, childNodes);
195.1811 +            else {
195.1812 +                ko.virtualElements.emptyNode(node);
195.1813 +                var endCommentNode = node.nextSibling; // Must be the next sibling, as we just emptied the children
195.1814 +                for (var i = 0, j = childNodes.length; i < j; i++)
195.1815 +                    endCommentNode.parentNode.insertBefore(childNodes[i], endCommentNode);
195.1816 +            }
195.1817 +        },
195.1818 +
195.1819 +        prepend: function(containerNode, nodeToPrepend) {
195.1820 +            if (!isStartComment(containerNode)) {
195.1821 +                if (containerNode.firstChild)
195.1822 +                    containerNode.insertBefore(nodeToPrepend, containerNode.firstChild);
195.1823 +                else
195.1824 +                    containerNode.appendChild(nodeToPrepend);
195.1825 +            } else {
195.1826 +                // Start comments must always have a parent and at least one following sibling (the end comment)
195.1827 +                containerNode.parentNode.insertBefore(nodeToPrepend, containerNode.nextSibling);
195.1828 +            }
195.1829 +        },
195.1830 +
195.1831 +        insertAfter: function(containerNode, nodeToInsert, insertAfterNode) {
195.1832 +            if (!insertAfterNode) {
195.1833 +                ko.virtualElements.prepend(containerNode, nodeToInsert);
195.1834 +            } else if (!isStartComment(containerNode)) {
195.1835 +                // Insert after insertion point
195.1836 +                if (insertAfterNode.nextSibling)
195.1837 +                    containerNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
195.1838 +                else
195.1839 +                    containerNode.appendChild(nodeToInsert);
195.1840 +            } else {
195.1841 +                // Children of start comments must always have a parent and at least one following sibling (the end comment)
195.1842 +                containerNode.parentNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
195.1843 +            }
195.1844 +        },
195.1845 +
195.1846 +        firstChild: function(node) {
195.1847 +            if (!isStartComment(node))
195.1848 +                return node.firstChild;
195.1849 +            if (!node.nextSibling || isEndComment(node.nextSibling))
195.1850 +                return null;
195.1851 +            return node.nextSibling;
195.1852 +        },
195.1853 +
195.1854 +        nextSibling: function(node) {
195.1855 +            if (isStartComment(node))
195.1856 +                node = getMatchingEndComment(node);
195.1857 +            if (node.nextSibling && isEndComment(node.nextSibling))
195.1858 +                return null;
195.1859 +            return node.nextSibling;
195.1860 +        },
195.1861 +
195.1862 +        virtualNodeBindingValue: function(node) {
195.1863 +            var regexMatch = isStartComment(node);
195.1864 +            return regexMatch ? regexMatch[1] : null;
195.1865 +        },
195.1866 +
195.1867 +        normaliseVirtualElementDomStructure: function(elementVerified) {
195.1868 +            // Workaround for https://github.com/SteveSanderson/knockout/issues/155
195.1869 +            // (IE <= 8 or IE 9 quirks mode parses your HTML weirdly, treating closing </li> tags as if they don't exist, thereby moving comment nodes
195.1870 +            // that are direct descendants of <ul> into the preceding <li>)
195.1871 +            if (!htmlTagsWithOptionallyClosingChildren[ko.utils.tagNameLower(elementVerified)])
195.1872 +                return;
195.1873 +
195.1874 +            // Scan immediate children to see if they contain unbalanced comment tags. If they do, those comment tags
195.1875 +            // must be intended to appear *after* that child, so move them there.
195.1876 +            var childNode = elementVerified.firstChild;
195.1877 +            if (childNode) {
195.1878 +                do {
195.1879 +                    if (childNode.nodeType === 1) {
195.1880 +                        var unbalancedTags = getUnbalancedChildTags(childNode);
195.1881 +                        if (unbalancedTags) {
195.1882 +                            // Fix up the DOM by moving the unbalanced tags to where they most likely were intended to be placed - *after* the child
195.1883 +                            var nodeToInsertBefore = childNode.nextSibling;
195.1884 +                            for (var i = 0; i < unbalancedTags.length; i++) {
195.1885 +                                if (nodeToInsertBefore)
195.1886 +                                    elementVerified.insertBefore(unbalancedTags[i], nodeToInsertBefore);
195.1887 +                                else
195.1888 +                                    elementVerified.appendChild(unbalancedTags[i]);
195.1889 +                            }
195.1890 +                        }
195.1891 +                    }
195.1892 +                } while (childNode = childNode.nextSibling);
195.1893 +            }
195.1894 +        }
195.1895 +    };
195.1896 +})();
195.1897 +ko.exportSymbol('virtualElements', ko.virtualElements);
195.1898 +ko.exportSymbol('virtualElements.allowedBindings', ko.virtualElements.allowedBindings);
195.1899 +ko.exportSymbol('virtualElements.emptyNode', ko.virtualElements.emptyNode);
195.1900 +//ko.exportSymbol('virtualElements.firstChild', ko.virtualElements.firstChild);     // firstChild is not minified
195.1901 +ko.exportSymbol('virtualElements.insertAfter', ko.virtualElements.insertAfter);
195.1902 +//ko.exportSymbol('virtualElements.nextSibling', ko.virtualElements.nextSibling);   // nextSibling is not minified
195.1903 +ko.exportSymbol('virtualElements.prepend', ko.virtualElements.prepend);
195.1904 +ko.exportSymbol('virtualElements.setDomNodeChildren', ko.virtualElements.setDomNodeChildren);
195.1905 +(function() {
195.1906 +    var defaultBindingAttributeName = "data-bind";
195.1907 +
195.1908 +    ko.bindingProvider = function() {
195.1909 +        this.bindingCache = {};
195.1910 +    };
195.1911 +
195.1912 +    ko.utils.extend(ko.bindingProvider.prototype, {
195.1913 +        'nodeHasBindings': function(node) {
195.1914 +            switch (node.nodeType) {
195.1915 +                case 1: return node.getAttribute(defaultBindingAttributeName) != null;   // Element
195.1916 +                case 8: return ko.virtualElements.virtualNodeBindingValue(node) != null; // Comment node
195.1917 +                default: return false;
195.1918 +            }
195.1919 +        },
195.1920 +
195.1921 +        'getBindings': function(node, bindingContext) {
195.1922 +            var bindingsString = this['getBindingsString'](node, bindingContext);
195.1923 +            return bindingsString ? this['parseBindingsString'](bindingsString, bindingContext, node) : null;
195.1924 +        },
195.1925 +
195.1926 +        // The following function is only used internally by this default provider.
195.1927 +        // It's not part of the interface definition for a general binding provider.
195.1928 +        'getBindingsString': function(node, bindingContext) {
195.1929 +            switch (node.nodeType) {
195.1930 +                case 1: return node.getAttribute(defaultBindingAttributeName);   // Element
195.1931 +                case 8: return ko.virtualElements.virtualNodeBindingValue(node); // Comment node
195.1932 +                default: return null;
195.1933 +            }
195.1934 +        },
195.1935 +
195.1936 +        // The following function is only used internally by this default provider.
195.1937 +        // It's not part of the interface definition for a general binding provider.
195.1938 +        'parseBindingsString': function(bindingsString, bindingContext, node) {
195.1939 +            try {
195.1940 +                var bindingFunction = createBindingsStringEvaluatorViaCache(bindingsString, this.bindingCache);
195.1941 +                return bindingFunction(bindingContext, node);
195.1942 +            } catch (ex) {
195.1943 +                throw new Error("Unable to parse bindings.\nMessage: " + ex + ";\nBindings value: " + bindingsString);
195.1944 +            }
195.1945 +        }
195.1946 +    });
195.1947 +
195.1948 +    ko.bindingProvider['instance'] = new ko.bindingProvider();
195.1949 +
195.1950 +    function createBindingsStringEvaluatorViaCache(bindingsString, cache) {
195.1951 +        var cacheKey = bindingsString;
195.1952 +        return cache[cacheKey]
195.1953 +            || (cache[cacheKey] = createBindingsStringEvaluator(bindingsString));
195.1954 +    }
195.1955 +
195.1956 +    function createBindingsStringEvaluator(bindingsString) {
195.1957 +        // Build the source for a function that evaluates "expression"
195.1958 +        // For each scope variable, add an extra level of "with" nesting
195.1959 +        // Example result: with(sc1) { with(sc0) { return (expression) } }
195.1960 +        var rewrittenBindings = ko.expressionRewriting.preProcessBindings(bindingsString),
195.1961 +            functionBody = "with($context){with($data||{}){return{" + rewrittenBindings + "}}}";
195.1962 +        return new Function("$context", "$element", functionBody);
195.1963 +    }
195.1964 +})();
195.1965 +
195.1966 +ko.exportSymbol('bindingProvider', ko.bindingProvider);
195.1967 +(function () {
195.1968 +    ko.bindingHandlers = {};
195.1969 +
195.1970 +    ko.bindingContext = function(dataItem, parentBindingContext, dataItemAlias) {
195.1971 +        if (parentBindingContext) {
195.1972 +            ko.utils.extend(this, parentBindingContext); // Inherit $root and any custom properties
195.1973 +            this['$parentContext'] = parentBindingContext;
195.1974 +            this['$parent'] = parentBindingContext['$data'];
195.1975 +            this['$parents'] = (parentBindingContext['$parents'] || []).slice(0);
195.1976 +            this['$parents'].unshift(this['$parent']);
195.1977 +        } else {
195.1978 +            this['$parents'] = [];
195.1979 +            this['$root'] = dataItem;
195.1980 +            // Export 'ko' in the binding context so it will be available in bindings and templates
195.1981 +            // even if 'ko' isn't exported as a global, such as when using an AMD loader.
195.1982 +            // See https://github.com/SteveSanderson/knockout/issues/490
195.1983 +            this['ko'] = ko;
195.1984 +        }
195.1985 +        this['$data'] = dataItem;
195.1986 +        if (dataItemAlias)
195.1987 +            this[dataItemAlias] = dataItem;
195.1988 +    }
195.1989 +    ko.bindingContext.prototype['createChildContext'] = function (dataItem, dataItemAlias) {
195.1990 +        return new ko.bindingContext(dataItem, this, dataItemAlias);
195.1991 +    };
195.1992 +    ko.bindingContext.prototype['extend'] = function(properties) {
195.1993 +        var clone = ko.utils.extend(new ko.bindingContext(), this);
195.1994 +        return ko.utils.extend(clone, properties);
195.1995 +    };
195.1996 +
195.1997 +    function validateThatBindingIsAllowedForVirtualElements(bindingName) {
195.1998 +        var validator = ko.virtualElements.allowedBindings[bindingName];
195.1999 +        if (!validator)
195.2000 +            throw new Error("The binding '" + bindingName + "' cannot be used with virtual elements")
195.2001 +    }
195.2002 +
195.2003 +    function applyBindingsToDescendantsInternal (viewModel, elementOrVirtualElement, bindingContextsMayDifferFromDomParentElement) {
195.2004 +        var currentChild, nextInQueue = ko.virtualElements.firstChild(elementOrVirtualElement);
195.2005 +        while (currentChild = nextInQueue) {
195.2006 +            // Keep a record of the next child *before* applying bindings, in case the binding removes the current child from its position
195.2007 +            nextInQueue = ko.virtualElements.nextSibling(currentChild);
195.2008 +            applyBindingsToNodeAndDescendantsInternal(viewModel, currentChild, bindingContextsMayDifferFromDomParentElement);
195.2009 +        }
195.2010 +    }
195.2011 +
195.2012 +    function applyBindingsToNodeAndDescendantsInternal (viewModel, nodeVerified, bindingContextMayDifferFromDomParentElement) {
195.2013 +        var shouldBindDescendants = true;
195.2014 +
195.2015 +        // Perf optimisation: Apply bindings only if...
195.2016 +        // (1) We need to store the binding context on this node (because it may differ from the DOM parent node's binding context)
195.2017 +        //     Note that we can't store binding contexts on non-elements (e.g., text nodes), as IE doesn't allow expando properties for those
195.2018 +        // (2) It might have bindings (e.g., it has a data-bind attribute, or it's a marker for a containerless template)
195.2019 +        var isElement = (nodeVerified.nodeType === 1);
195.2020 +        if (isElement) // Workaround IE <= 8 HTML parsing weirdness
195.2021 +            ko.virtualElements.normaliseVirtualElementDomStructure(nodeVerified);
195.2022 +
195.2023 +        var shouldApplyBindings = (isElement && bindingContextMayDifferFromDomParentElement)             // Case (1)
195.2024 +                               || ko.bindingProvider['instance']['nodeHasBindings'](nodeVerified);       // Case (2)
195.2025 +        if (shouldApplyBindings)
195.2026 +            shouldBindDescendants = applyBindingsToNodeInternal(nodeVerified, null, viewModel, bindingContextMayDifferFromDomParentElement).shouldBindDescendants;
195.2027 +
195.2028 +        if (shouldBindDescendants) {
195.2029 +            // We're recursing automatically into (real or virtual) child nodes without changing binding contexts. So,
195.2030 +            //  * For children of a *real* element, the binding context is certainly the same as on their DOM .parentNode,
195.2031 +            //    hence bindingContextsMayDifferFromDomParentElement is false
195.2032 +            //  * For children of a *virtual* element, we can't be sure. Evaluating .parentNode on those children may
195.2033 +            //    skip over any number of intermediate virtual elements, any of which might define a custom binding context,
195.2034 +            //    hence bindingContextsMayDifferFromDomParentElement is true
195.2035 +            applyBindingsToDescendantsInternal(viewModel, nodeVerified, /* bindingContextsMayDifferFromDomParentElement: */ !isElement);
195.2036 +        }
195.2037 +    }
195.2038 +
195.2039 +    function applyBindingsToNodeInternal (node, bindings, viewModelOrBindingContext, bindingContextMayDifferFromDomParentElement) {
195.2040 +        // Need to be sure that inits are only run once, and updates never run until all the inits have been run
195.2041 +        var initPhase = 0; // 0 = before all inits, 1 = during inits, 2 = after all inits
195.2042 +
195.2043 +        // Each time the dependentObservable is evaluated (after data changes),
195.2044 +        // the binding attribute is reparsed so that it can pick out the correct
195.2045 +        // model properties in the context of the changed data.
195.2046 +        // DOM event callbacks need to be able to access this changed data,
195.2047 +        // so we need a single parsedBindings variable (shared by all callbacks
195.2048 +        // associated with this node's bindings) that all the closures can access.
195.2049 +        var parsedBindings;
195.2050 +        function makeValueAccessor(bindingKey) {
195.2051 +            return function () { return parsedBindings[bindingKey] }
195.2052 +        }
195.2053 +        function parsedBindingsAccessor() {
195.2054 +            return parsedBindings;
195.2055 +        }
195.2056 +
195.2057 +        var bindingHandlerThatControlsDescendantBindings;
195.2058 +        ko.dependentObservable(
195.2059 +            function () {
195.2060 +                // Ensure we have a nonnull binding context to work with
195.2061 +                var bindingContextInstance = viewModelOrBindingContext && (viewModelOrBindingContext instanceof ko.bindingContext)
195.2062 +                    ? viewModelOrBindingContext
195.2063 +                    : new ko.bindingContext(ko.utils.unwrapObservable(viewModelOrBindingContext));
195.2064 +                var viewModel = bindingContextInstance['$data'];
195.2065 +
195.2066 +                // Optimization: Don't store the binding context on this node if it's definitely the same as on node.parentNode, because
195.2067 +                // we can easily recover it just by scanning up the node's ancestors in the DOM
195.2068 +                // (note: here, parent node means "real DOM parent" not "virtual parent", as there's no O(1) way to find the virtual parent)
195.2069 +                if (bindingContextMayDifferFromDomParentElement)
195.2070 +                    ko.storedBindingContextForNode(node, bindingContextInstance);
195.2071 +
195.2072 +                // Use evaluatedBindings if given, otherwise fall back on asking the bindings provider to give us some bindings
195.2073 +                var evaluatedBindings = (typeof bindings == "function") ? bindings(bindingContextInstance, node) : bindings;
195.2074 +                parsedBindings = evaluatedBindings || ko.bindingProvider['instance']['getBindings'](node, bindingContextInstance);
195.2075 +
195.2076 +                if (parsedBindings) {
195.2077 +                    // First run all the inits, so bindings can register for notification on changes
195.2078 +                    if (initPhase === 0) {
195.2079 +                        initPhase = 1;
195.2080 +                        for (var bindingKey in parsedBindings) {
195.2081 +                            var binding = ko.bindingHandlers[bindingKey];
195.2082 +                            if (binding && node.nodeType === 8)
195.2083 +                                validateThatBindingIsAllowedForVirtualElements(bindingKey);
195.2084 +
195.2085 +                            if (binding && typeof binding["init"] == "function") {
195.2086 +                                var handlerInitFn = binding["init"];
195.2087 +                                var initResult = handlerInitFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
195.2088 +
195.2089 +                                // If this binding handler claims to control descendant bindings, make a note of this
195.2090 +                                if (initResult && initResult['controlsDescendantBindings']) {
195.2091 +                                    if (bindingHandlerThatControlsDescendantBindings !== undefined)
195.2092 +                                        throw new Error("Multiple bindings (" + bindingHandlerThatControlsDescendantBindings + " and " + bindingKey + ") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.");
195.2093 +                                    bindingHandlerThatControlsDescendantBindings = bindingKey;
195.2094 +                                }
195.2095 +                            }
195.2096 +                        }
195.2097 +                        initPhase = 2;
195.2098 +                    }
195.2099 +
195.2100 +                    // ... then run all the updates, which might trigger changes even on the first evaluation
195.2101 +                    if (initPhase === 2) {
195.2102 +                        for (var bindingKey in parsedBindings) {
195.2103 +                            var binding = ko.bindingHandlers[bindingKey];
195.2104 +                            if (binding && typeof binding["update"] == "function") {
195.2105 +                                var handlerUpdateFn = binding["update"];
195.2106 +                                handlerUpdateFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
195.2107 +                            }
195.2108 +                        }
195.2109 +                    }
195.2110 +                }
195.2111 +            },
195.2112 +            null,
195.2113 +            { disposeWhenNodeIsRemoved : node }
195.2114 +        );
195.2115 +
195.2116 +        return {
195.2117 +            shouldBindDescendants: bindingHandlerThatControlsDescendantBindings === undefined
195.2118 +        };
195.2119 +    };
195.2120 +
195.2121 +    var storedBindingContextDomDataKey = "__ko_bindingContext__";
195.2122 +    ko.storedBindingContextForNode = function (node, bindingContext) {
195.2123 +        if (arguments.length == 2)
195.2124 +            ko.utils.domData.set(node, storedBindingContextDomDataKey, bindingContext);
195.2125 +        else
195.2126 +            return ko.utils.domData.get(node, storedBindingContextDomDataKey);
195.2127 +    }
195.2128 +
195.2129 +    ko.applyBindingsToNode = function (node, bindings, viewModel) {
195.2130 +        if (node.nodeType === 1) // If it's an element, workaround IE <= 8 HTML parsing weirdness
195.2131 +            ko.virtualElements.normaliseVirtualElementDomStructure(node);
195.2132 +        return applyBindingsToNodeInternal(node, bindings, viewModel, true);
195.2133 +    };
195.2134 +
195.2135 +    ko.applyBindingsToDescendants = function(viewModel, rootNode) {
195.2136 +        if (rootNode.nodeType === 1 || rootNode.nodeType === 8)
195.2137 +            applyBindingsToDescendantsInternal(viewModel, rootNode, true);
195.2138 +    };
195.2139 +
195.2140 +    ko.applyBindings = function (viewModel, rootNode) {
195.2141 +        if (rootNode && (rootNode.nodeType !== 1) && (rootNode.nodeType !== 8))
195.2142 +            throw new Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");
195.2143 +        rootNode = rootNode || window.document.body; // Make "rootNode" parameter optional
195.2144 +
195.2145 +        applyBindingsToNodeAndDescendantsInternal(viewModel, rootNode, true);
195.2146 +    };
195.2147 +
195.2148 +    // Retrieving binding context from arbitrary nodes
195.2149 +    ko.contextFor = function(node) {
195.2150 +        // We can only do something meaningful for elements and comment nodes (in particular, not text nodes, as IE can't store domdata for them)
195.2151 +        switch (node.nodeType) {
195.2152 +            case 1:
195.2153 +            case 8:
195.2154 +                var context = ko.storedBindingContextForNode(node);
195.2155 +                if (context) return context;
195.2156 +                if (node.parentNode) return ko.contextFor(node.parentNode);
195.2157 +                break;
195.2158 +        }
195.2159 +        return undefined;
195.2160 +    };
195.2161 +    ko.dataFor = function(node) {
195.2162 +        var context = ko.contextFor(node);
195.2163 +        return context ? context['$data'] : undefined;
195.2164 +    };
195.2165 +
195.2166 +    ko.exportSymbol('bindingHandlers', ko.bindingHandlers);
195.2167 +    ko.exportSymbol('applyBindings', ko.applyBindings);
195.2168 +    ko.exportSymbol('applyBindingsToDescendants', ko.applyBindingsToDescendants);
195.2169 +    ko.exportSymbol('applyBindingsToNode', ko.applyBindingsToNode);
195.2170 +    ko.exportSymbol('contextFor', ko.contextFor);
195.2171 +    ko.exportSymbol('dataFor', ko.dataFor);
195.2172 +})();
195.2173 +var attrHtmlToJavascriptMap = { 'class': 'className', 'for': 'htmlFor' };
195.2174 +ko.bindingHandlers['attr'] = {
195.2175 +    'update': function(element, valueAccessor, allBindingsAccessor) {
195.2176 +        var value = ko.utils.unwrapObservable(valueAccessor()) || {};
195.2177 +        for (var attrName in value) {
195.2178 +            if (typeof attrName == "string") {
195.2179 +                var attrValue = ko.utils.unwrapObservable(value[attrName]);
195.2180 +
195.2181 +                // To cover cases like "attr: { checked:someProp }", we want to remove the attribute entirely
195.2182 +                // when someProp is a "no value"-like value (strictly null, false, or undefined)
195.2183 +                // (because the absence of the "checked" attr is how to mark an element as not checked, etc.)
195.2184 +                var toRemove = (attrValue === false) || (attrValue === null) || (attrValue === undefined);
195.2185 +                if (toRemove)
195.2186 +                    element.removeAttribute(attrName);
195.2187 +
195.2188 +                // In IE <= 7 and IE8 Quirks Mode, you have to use the Javascript property name instead of the
195.2189 +                // HTML attribute name for certain attributes. IE8 Standards Mode supports the correct behavior,
195.2190 +                // but instead of figuring out the mode, we'll just set the attribute through the Javascript
195.2191 +                // property for IE <= 8.
195.2192 +                if (ko.utils.ieVersion <= 8 && attrName in attrHtmlToJavascriptMap) {
195.2193 +                    attrName = attrHtmlToJavascriptMap[attrName];
195.2194 +                    if (toRemove)
195.2195 +                        element.removeAttribute(attrName);
195.2196 +                    else
195.2197 +                        element[attrName] = attrValue;
195.2198 +                } else if (!toRemove) {
195.2199 +                    try {
195.2200 +                        element.setAttribute(attrName, attrValue.toString());
195.2201 +                    } catch (err) {
195.2202 +                        // ignore for now
195.2203 +                        if (console) {
195.2204 +                            console.log("Can't set attribute " + attrName + " to " + attrValue + " error: " + err);
195.2205 +                        }
195.2206 +                    }
195.2207 +                }
195.2208 +
195.2209 +                // Treat "name" specially - although you can think of it as an attribute, it also needs
195.2210 +                // special handling on older versions of IE (https://github.com/SteveSanderson/knockout/pull/333)
195.2211 +                // Deliberately being case-sensitive here because XHTML would regard "Name" as a different thing
195.2212 +                // entirely, and there's no strong reason to allow for such casing in HTML.
195.2213 +                if (attrName === "name") {
195.2214 +                    ko.utils.setElementName(element, toRemove ? "" : attrValue.toString());
195.2215 +                }
195.2216 +            }
195.2217 +        }
195.2218 +    }
195.2219 +};
195.2220 +ko.bindingHandlers['checked'] = {
195.2221 +    'init': function (element, valueAccessor, allBindingsAccessor) {
195.2222 +        var updateHandler = function() {
195.2223 +            var valueToWrite;
195.2224 +            if (element.type == "checkbox") {
195.2225 +                valueToWrite = element.checked;
195.2226 +            } else if ((element.type == "radio") && (element.checked)) {
195.2227 +                valueToWrite = element.value;
195.2228 +            } else {
195.2229 +                return; // "checked" binding only responds to checkboxes and selected radio buttons
195.2230 +            }
195.2231 +
195.2232 +            var modelValue = valueAccessor(), unwrappedValue = ko.utils.unwrapObservable(modelValue);
195.2233 +            if ((element.type == "checkbox") && (unwrappedValue instanceof Array)) {
195.2234 +                // For checkboxes bound to an array, we add/remove the checkbox value to that array
195.2235 +                // This works for both observable and non-observable arrays
195.2236 +                var existingEntryIndex = ko.utils.arrayIndexOf(unwrappedValue, element.value);
195.2237 +                if (element.checked && (existingEntryIndex < 0))
195.2238 +                    modelValue.push(element.value);
195.2239 +                else if ((!element.checked) && (existingEntryIndex >= 0))
195.2240 +                    modelValue.splice(existingEntryIndex, 1);
195.2241 +            } else {
195.2242 +                ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'checked', valueToWrite, true);
195.2243 +            }
195.2244 +        };
195.2245 +        ko.utils.registerEventHandler(element, "click", updateHandler);
195.2246 +
195.2247 +        // IE 6 won't allow radio buttons to be selected unless they have a name
195.2248 +        if ((element.type == "radio") && !element.name)
195.2249 +            ko.bindingHandlers['uniqueName']['init'](element, function() { return true });
195.2250 +    },
195.2251 +    'update': function (element, valueAccessor) {
195.2252 +        var value = ko.utils.unwrapObservable(valueAccessor());
195.2253 +
195.2254 +        if (element.type == "checkbox") {
195.2255 +            if (value instanceof Array) {
195.2256 +                // When bound to an array, the checkbox being checked represents its value being present in that array
195.2257 +                element.checked = ko.utils.arrayIndexOf(value, element.value) >= 0;
195.2258 +            } else {
195.2259 +                // When bound to anything other value (not an array), the checkbox being checked represents the value being trueish
195.2260 +                element.checked = value;
195.2261 +            }
195.2262 +        } else if (element.type == "radio") {
195.2263 +            element.checked = (element.value == value);
195.2264 +        }
195.2265 +    }
195.2266 +};
195.2267 +var classesWrittenByBindingKey = '__ko__cssValue';
195.2268 +ko.bindingHandlers['css'] = {
195.2269 +    'update': function (element, valueAccessor) {
195.2270 +        var value = ko.utils.unwrapObservable(valueAccessor());
195.2271 +        if (typeof value == "object") {
195.2272 +            for (var className in value) {
195.2273 +                var shouldHaveClass = ko.utils.unwrapObservable(value[className]);
195.2274 +                ko.utils.toggleDomNodeCssClass(element, className, shouldHaveClass);
195.2275 +            }
195.2276 +        } else {
195.2277 +            value = String(value || ''); // Make sure we don't try to store or set a non-string value
195.2278 +            ko.utils.toggleDomNodeCssClass(element, element[classesWrittenByBindingKey], false);
195.2279 +            element[classesWrittenByBindingKey] = value;
195.2280 +            ko.utils.toggleDomNodeCssClass(element, value, true);
195.2281 +        }
195.2282 +    }
195.2283 +};
195.2284 +ko.bindingHandlers['enable'] = {
195.2285 +    'update': function (element, valueAccessor) {
195.2286 +        var value = ko.utils.unwrapObservable(valueAccessor());
195.2287 +        if (value && element.disabled)
195.2288 +            element.removeAttribute("disabled");
195.2289 +        else if ((!value) && (!element.disabled))
195.2290 +            element.disabled = true;
195.2291 +    }
195.2292 +};
195.2293 +
195.2294 +ko.bindingHandlers['disable'] = {
195.2295 +    'update': function (element, valueAccessor) {
195.2296 +        ko.bindingHandlers['enable']['update'](element, function() { return !ko.utils.unwrapObservable(valueAccessor()) });
195.2297 +    }
195.2298 +};
195.2299 +// For certain common events (currently just 'click'), allow a simplified data-binding syntax
195.2300 +// e.g. click:handler instead of the usual full-length event:{click:handler}
195.2301 +function makeEventHandlerShortcut(eventName) {
195.2302 +    ko.bindingHandlers[eventName] = {
195.2303 +        'init': function(element, valueAccessor, allBindingsAccessor, viewModel) {
195.2304 +            var newValueAccessor = function () {
195.2305 +                var result = {};
195.2306 +                result[eventName] = valueAccessor();
195.2307 +                return result;
195.2308 +            };
195.2309 +            return ko.bindingHandlers['event']['init'].call(this, element, newValueAccessor, allBindingsAccessor, viewModel);
195.2310 +        }
195.2311 +    }
195.2312 +}
195.2313 +
195.2314 +ko.bindingHandlers['event'] = {
195.2315 +    'init' : function (element, valueAccessor, allBindingsAccessor, viewModel) {
195.2316 +        var eventsToHandle = valueAccessor() || {};
195.2317 +        for(var eventNameOutsideClosure in eventsToHandle) {
195.2318 +            (function() {
195.2319 +                var eventName = eventNameOutsideClosure; // Separate variable to be captured by event handler closure
195.2320 +                if (typeof eventName == "string") {
195.2321 +                    ko.utils.registerEventHandler(element, eventName, function (event) {
195.2322 +                        var handlerReturnValue;
195.2323 +                        var handlerFunction = valueAccessor()[eventName];
195.2324 +                        if (!handlerFunction)
195.2325 +                            return;
195.2326 +                        var allBindings = allBindingsAccessor();
195.2327 +
195.2328 +                        try {
195.2329 +                            // Take all the event args, and prefix with the viewmodel
195.2330 +                            var argsForHandler = ko.utils.makeArray(arguments);
195.2331 +                            argsForHandler.unshift(viewModel);
195.2332 +                            handlerReturnValue = handlerFunction.apply(viewModel, argsForHandler);
195.2333 +                        } finally {
195.2334 +                            if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
195.2335 +                                if (event.preventDefault)
195.2336 +                                    event.preventDefault();
195.2337 +                                else
195.2338 +                                    event.returnValue = false;
195.2339 +                            }
195.2340 +                        }
195.2341 +
195.2342 +                        var bubble = allBindings[eventName + 'Bubble'] !== false;
195.2343 +                        if (!bubble) {
195.2344 +                            event.cancelBubble = true;
195.2345 +                            if (event.stopPropagation)
195.2346 +                                event.stopPropagation();
195.2347 +                        }
195.2348 +                    });
195.2349 +                }
195.2350 +            })();
195.2351 +        }
195.2352 +    }
195.2353 +};
195.2354 +// "foreach: someExpression" is equivalent to "template: { foreach: someExpression }"
195.2355 +// "foreach: { data: someExpression, afterAdd: myfn }" is equivalent to "template: { foreach: someExpression, afterAdd: myfn }"
195.2356 +ko.bindingHandlers['foreach'] = {
195.2357 +    makeTemplateValueAccessor: function(valueAccessor) {
195.2358 +        return function() {
195.2359 +            var modelValue = valueAccessor(),
195.2360 +                unwrappedValue = ko.utils.peekObservable(modelValue);    // Unwrap without setting a dependency here
195.2361 +
195.2362 +            // If unwrappedValue is the array, pass in the wrapped value on its own
195.2363 +            // The value will be unwrapped and tracked within the template binding
195.2364 +            // (See https://github.com/SteveSanderson/knockout/issues/523)
195.2365 +            if ((!unwrappedValue) || typeof unwrappedValue.length == "number")
195.2366 +                return { 'foreach': modelValue, 'templateEngine': ko.nativeTemplateEngine.instance };
195.2367 +
195.2368 +            // If unwrappedValue.data is the array, preserve all relevant options and unwrap again value so we get updates
195.2369 +            ko.utils.unwrapObservable(modelValue);
195.2370 +            return {
195.2371 +                'foreach': unwrappedValue['data'],
195.2372 +                'as': unwrappedValue['as'],
195.2373 +                'includeDestroyed': unwrappedValue['includeDestroyed'],
195.2374 +                'afterAdd': unwrappedValue['afterAdd'],
195.2375 +                'beforeRemove': unwrappedValue['beforeRemove'],
195.2376 +                'afterRender': unwrappedValue['afterRender'],
195.2377 +                'beforeMove': unwrappedValue['beforeMove'],
195.2378 +                'afterMove': unwrappedValue['afterMove'],
195.2379 +                'templateEngine': ko.nativeTemplateEngine.instance
195.2380 +            };
195.2381 +        };
195.2382 +    },
195.2383 +    'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
195.2384 +        return ko.bindingHandlers['template']['init'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor));
195.2385 +    },
195.2386 +    'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
195.2387 +        return ko.bindingHandlers['template']['update'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor), allBindingsAccessor, viewModel, bindingContext);
195.2388 +    }
195.2389 +};
195.2390 +ko.expressionRewriting.bindingRewriteValidators['foreach'] = false; // Can't rewrite control flow bindings
195.2391 +ko.virtualElements.allowedBindings['foreach'] = true;
195.2392 +var hasfocusUpdatingProperty = '__ko_hasfocusUpdating';
195.2393 +ko.bindingHandlers['hasfocus'] = {
195.2394 +    'init': function(element, valueAccessor, allBindingsAccessor) {
195.2395 +        var handleElementFocusChange = function(isFocused) {
195.2396 +            // Where possible, ignore which event was raised and determine focus state using activeElement,
195.2397 +            // as this avoids phantom focus/blur events raised when changing tabs in modern browsers.
195.2398 +            // However, not all KO-targeted browsers (Firefox 2) support activeElement. For those browsers,
195.2399 +            // prevent a loss of focus when changing tabs/windows by setting a flag that prevents hasfocus
195.2400 +            // from calling 'blur()' on the element when it loses focus.
195.2401 +            // Discussion at https://github.com/SteveSanderson/knockout/pull/352
195.2402 +            element[hasfocusUpdatingProperty] = true;
195.2403 +            var ownerDoc = element.ownerDocument;
195.2404 +            if ("activeElement" in ownerDoc) {
195.2405 +                isFocused = (ownerDoc.activeElement === element);
195.2406 +            }
195.2407 +            var modelValue = valueAccessor();
195.2408 +            ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'hasfocus', isFocused, true);
195.2409 +            element[hasfocusUpdatingProperty] = false;
195.2410 +        };
195.2411 +        var handleElementFocusIn = handleElementFocusChange.bind(null, true);
195.2412 +        var handleElementFocusOut = handleElementFocusChange.bind(null, false);
195.2413 +
195.2414 +        ko.utils.registerEventHandler(element, "focus", handleElementFocusIn);
195.2415 +        ko.utils.registerEventHandler(element, "focusin", handleElementFocusIn); // For IE
195.2416 +        ko.utils.registerEventHandler(element, "blur",  handleElementFocusOut);
195.2417 +        ko.utils.registerEventHandler(element, "focusout",  handleElementFocusOut); // For IE
195.2418 +    },
195.2419 +    'update': function(element, valueAccessor) {
195.2420 +        var value = ko.utils.unwrapObservable(valueAccessor());
195.2421 +        if (!element[hasfocusUpdatingProperty]) {
195.2422 +            value ? element.focus() : element.blur();
195.2423 +            ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, value ? "focusin" : "focusout"]); // For IE, which doesn't reliably fire "focus" or "blur" events synchronously
195.2424 +        }
195.2425 +    }
195.2426 +};
195.2427 +ko.bindingHandlers['html'] = {
195.2428 +    'init': function() {
195.2429 +        // Prevent binding on the dynamically-injected HTML (as developers are unlikely to expect that, and it has security implications)
195.2430 +        return { 'controlsDescendantBindings': true };
195.2431 +    },
195.2432 +    'update': function (element, valueAccessor) {
195.2433 +        // setHtml will unwrap the value if needed
195.2434 +        ko.utils.setHtml(element, valueAccessor());
195.2435 +    }
195.2436 +};
195.2437 +var withIfDomDataKey = '__ko_withIfBindingData';
195.2438 +// Makes a binding like with or if
195.2439 +function makeWithIfBinding(bindingKey, isWith, isNot, makeContextCallback) {
195.2440 +    ko.bindingHandlers[bindingKey] = {
195.2441 +        'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
195.2442 +            ko.utils.domData.set(element, withIfDomDataKey, {});
195.2443 +            return { 'controlsDescendantBindings': true };
195.2444 +        },
195.2445 +        'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
195.2446 +            var withIfData = ko.utils.domData.get(element, withIfDomDataKey),
195.2447 +                dataValue = ko.utils.unwrapObservable(valueAccessor()),
195.2448 +                shouldDisplay = !isNot !== !dataValue, // equivalent to isNot ? !dataValue : !!dataValue
195.2449 +                isFirstRender = !withIfData.savedNodes,
195.2450 +                needsRefresh = isFirstRender || isWith || (shouldDisplay !== withIfData.didDisplayOnLastUpdate);
195.2451 +
195.2452 +            if (needsRefresh) {
195.2453 +                if (isFirstRender) {
195.2454 +                    withIfData.savedNodes = ko.utils.cloneNodes(ko.virtualElements.childNodes(element), true /* shouldCleanNodes */);
195.2455 +                }
195.2456 +
195.2457 +                if (shouldDisplay) {
195.2458 +                    if (!isFirstRender) {
195.2459 +                        ko.virtualElements.setDomNodeChildren(element, ko.utils.cloneNodes(withIfData.savedNodes));
195.2460 +                    }
195.2461 +                    ko.applyBindingsToDescendants(makeContextCallback ? makeContextCallback(bindingContext, dataValue) : bindingContext, element);
195.2462 +                } else {
195.2463 +                    ko.virtualElements.emptyNode(element);
195.2464 +                }
195.2465 +
195.2466 +                withIfData.didDisplayOnLastUpdate = shouldDisplay;
195.2467 +            }
195.2468 +        }
195.2469 +    };
195.2470 +    ko.expressionRewriting.bindingRewriteValidators[bindingKey] = false; // Can't rewrite control flow bindings
195.2471 +    ko.virtualElements.allowedBindings[bindingKey] = true;
195.2472 +}
195.2473 +
195.2474 +// Construct the actual binding handlers
195.2475 +makeWithIfBinding('if');
195.2476 +makeWithIfBinding('ifnot', false /* isWith */, true /* isNot */);
195.2477 +makeWithIfBinding('with', true /* isWith */, false /* isNot */,
195.2478 +    function(bindingContext, dataValue) {
195.2479 +        return bindingContext['createChildContext'](dataValue);
195.2480 +    }
195.2481 +);
195.2482 +function ensureDropdownSelectionIsConsistentWithModelValue(element, modelValue, preferModelValue) {
195.2483 +    if (preferModelValue) {
195.2484 +        if (modelValue !== ko.selectExtensions.readValue(element))
195.2485 +            ko.selectExtensions.writeValue(element, modelValue);
195.2486 +    }
195.2487 +
195.2488 +    // No matter which direction we're syncing in, we want the end result to be equality between dropdown value and model value.
195.2489 +    // If they aren't equal, either we prefer the dropdown value, or the model value couldn't be represented, so either way,
195.2490 +    // change the model value to match the dropdown.
195.2491 +    if (modelValue !== ko.selectExtensions.readValue(element))
195.2492 +        ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, "change"]);
195.2493 +};
195.2494 +
195.2495 +ko.bindingHandlers['options'] = {
195.2496 +    'update': function (element, valueAccessor, allBindingsAccessor) {
195.2497 +        if (ko.utils.tagNameLower(element) !== "select")
195.2498 +            throw new Error("options binding applies only to SELECT elements");
195.2499 +
195.2500 +        var selectWasPreviouslyEmpty = element.length == 0;
195.2501 +        var previousSelectedValues = ko.utils.arrayMap(ko.utils.arrayFilter(element.childNodes, function (node) {
195.2502 +            return node.tagName && (ko.utils.tagNameLower(node) === "option") && node.selected;
195.2503 +        }), function (node) {
195.2504 +            return ko.selectExtensions.readValue(node) || node.innerText || node.textContent;
195.2505 +        });
195.2506 +        var previousScrollTop = element.scrollTop;
195.2507 +
195.2508 +        var value = ko.utils.unwrapObservable(valueAccessor());
195.2509 +        var selectedValue = element.value;
195.2510 +
195.2511 +        // Remove all existing <option>s.
195.2512 +        // Need to use .remove() rather than .removeChild() for <option>s otherwise IE behaves oddly (https://github.com/SteveSanderson/knockout/issues/134)
195.2513 +        while (element.length > 0) {
195.2514 +            ko.cleanNode(element.options[0]);
195.2515 +            element.remove(0);
195.2516 +        }
195.2517 +
195.2518 +        if (value) {
195.2519 +            var allBindings = allBindingsAccessor(),
195.2520 +                includeDestroyed = allBindings['optionsIncludeDestroyed'];
195.2521 +
195.2522 +            if (typeof value.length != "number")
195.2523 +                value = [value];
195.2524 +            if (allBindings['optionsCaption']) {
195.2525 +                var option = document.createElement("option");
195.2526 +                ko.utils.setHtml(option, allBindings['optionsCaption']);
195.2527 +                ko.selectExtensions.writeValue(option, undefined);
195.2528 +                element.appendChild(option);
195.2529 +            }
195.2530 +
195.2531 +            for (var i = 0, j = value.length; i < j; i++) {
195.2532 +                // Skip destroyed items
195.2533 +                var arrayEntry = value[i];
195.2534 +                if (arrayEntry && arrayEntry['_destroy'] && !includeDestroyed)
195.2535 +                    continue;
195.2536 +
195.2537 +                var option = document.createElement("option");
195.2538 +
195.2539 +                function applyToObject(object, predicate, defaultValue) {
195.2540 +                    var predicateType = typeof predicate;
195.2541 +                    if (predicateType == "function")    // Given a function; run it against the data value
195.2542 +                        return predicate(object);
195.2543 +                    else if (predicateType == "string") // Given a string; treat it as a property name on the data value
195.2544 +                        return object[predicate];
195.2545 +                    else                                // Given no optionsText arg; use the data value itself
195.2546 +                        return defaultValue;
195.2547 +                }
195.2548 +
195.2549 +                // Apply a value to the option element
195.2550 +                var optionValue = applyToObject(arrayEntry, allBindings['optionsValue'], arrayEntry);
195.2551 +                ko.selectExtensions.writeValue(option, ko.utils.unwrapObservable(optionValue));
195.2552 +
195.2553 +                // Apply some text to the option element
195.2554 +                var optionText = applyToObject(arrayEntry, allBindings['optionsText'], optionValue);
195.2555 +                ko.utils.setTextContent(option, optionText);
195.2556 +
195.2557 +                element.appendChild(option);
195.2558 +            }
195.2559 +
195.2560 +            // IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document.
195.2561 +            // That's why we first added them without selection. Now it's time to set the selection.
195.2562 +            var newOptions = element.getElementsByTagName("option");
195.2563 +            var countSelectionsRetained = 0;
195.2564 +            for (var i = 0, j = newOptions.length; i < j; i++) {
195.2565 +                if (ko.utils.arrayIndexOf(previousSelectedValues, ko.selectExtensions.readValue(newOptions[i])) >= 0) {
195.2566 +                    ko.utils.setOptionNodeSelectionState(newOptions[i], true);
195.2567 +                    countSelectionsRetained++;
195.2568 +                }
195.2569 +            }
195.2570 +
195.2571 +            element.scrollTop = previousScrollTop;
195.2572 +
195.2573 +            if (selectWasPreviouslyEmpty && ('value' in allBindings)) {
195.2574 +                // Ensure consistency between model value and selected option.
195.2575 +                // If the dropdown is being populated for the first time here (or was otherwise previously empty),
195.2576 +                // the dropdown selection state is meaningless, so we preserve the model value.
195.2577 +                ensureDropdownSelectionIsConsistentWithModelValue(element, ko.utils.peekObservable(allBindings['value']), /* preferModelValue */ true);
195.2578 +            }
195.2579 +
195.2580 +            // Workaround for IE9 bug
195.2581 +            ko.utils.ensureSelectElementIsRenderedCorrectly(element);
195.2582 +        }
195.2583 +    }
195.2584 +};
195.2585 +ko.bindingHandlers['options'].optionValueDomDataKey = '__ko.optionValueDomData__';
195.2586 +ko.bindingHandlers['selectedOptions'] = {
195.2587 +    'init': function (element, valueAccessor, allBindingsAccessor) {
195.2588 +        ko.utils.registerEventHandler(element, "change", function () {
195.2589 +            var value = valueAccessor(), valueToWrite = [];
195.2590 +            ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
195.2591 +                if (node.selected)
195.2592 +                    valueToWrite.push(ko.selectExtensions.readValue(node));
195.2593 +            });
195.2594 +            ko.expressionRewriting.writeValueToProperty(value, allBindingsAccessor, 'value', valueToWrite);
195.2595 +        });
195.2596 +    },
195.2597 +    'update': function (element, valueAccessor) {
195.2598 +        if (ko.utils.tagNameLower(element) != "select")
195.2599 +            throw new Error("values binding applies only to SELECT elements");
195.2600 +
195.2601 +        var newValue = ko.utils.unwrapObservable(valueAccessor());
195.2602 +        if (newValue && typeof newValue.length == "number") {
195.2603 +            ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
195.2604 +                var isSelected = ko.utils.arrayIndexOf(newValue, ko.selectExtensions.readValue(node)) >= 0;
195.2605 +                ko.utils.setOptionNodeSelectionState(node, isSelected);
195.2606 +            });
195.2607 +        }
195.2608 +    }
195.2609 +};
195.2610 +ko.bindingHandlers['style'] = {
195.2611 +    'update': function (element, valueAccessor) {
195.2612 +        var value = ko.utils.unwrapObservable(valueAccessor() || {});
195.2613 +        for (var styleName in value) {
195.2614 +            if (typeof styleName == "string") {
195.2615 +                var styleValue = ko.utils.unwrapObservable(value[styleName]);
195.2616 +                element.style[styleName] = styleValue || ""; // Empty string removes the value, whereas null/undefined have no effect
195.2617 +            }
195.2618 +        }
195.2619 +    }
195.2620 +};
195.2621 +ko.bindingHandlers['submit'] = {
195.2622 +    'init': function (element, valueAccessor, allBindingsAccessor, viewModel) {
195.2623 +        if (typeof valueAccessor() != "function")
195.2624 +            throw new Error("The value for a submit binding must be a function");
195.2625 +        ko.utils.registerEventHandler(element, "submit", function (event) {
195.2626 +            var handlerReturnValue;
195.2627 +            var value = valueAccessor();
195.2628 +            try { handlerReturnValue = value.call(viewModel, element); }
195.2629 +            finally {
195.2630 +                if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
195.2631 +                    if (event.preventDefault)
195.2632 +                        event.preventDefault();
195.2633 +                    else
195.2634 +                        event.returnValue = false;
195.2635 +                }
195.2636 +            }
195.2637 +        });
195.2638 +    }
195.2639 +};
195.2640 +ko.bindingHandlers['text'] = {
195.2641 +    'update': function (element, valueAccessor) {
195.2642 +        ko.utils.setTextContent(element, valueAccessor());
195.2643 +    }
195.2644 +};
195.2645 +ko.virtualElements.allowedBindings['text'] = true;
195.2646 +ko.bindingHandlers['uniqueName'] = {
195.2647 +    'init': function (element, valueAccessor) {
195.2648 +        if (valueAccessor()) {
195.2649 +            var name = "ko_unique_" + (++ko.bindingHandlers['uniqueName'].currentIndex);
195.2650 +            ko.utils.setElementName(element, name);
195.2651 +        }
195.2652 +    }
195.2653 +};
195.2654 +ko.bindingHandlers['uniqueName'].currentIndex = 0;
195.2655 +ko.bindingHandlers['value'] = {
195.2656 +    'init': function (element, valueAccessor, allBindingsAccessor) {
195.2657 +        // Always catch "change" event; possibly other events too if asked
195.2658 +        var eventsToCatch = ["change"];
195.2659 +        var requestedEventsToCatch = allBindingsAccessor()["valueUpdate"];
195.2660 +        var propertyChangedFired = false;
195.2661 +        if (requestedEventsToCatch) {
195.2662 +            if (typeof requestedEventsToCatch == "string") // Allow both individual event names, and arrays of event names
195.2663 +                requestedEventsToCatch = [requestedEventsToCatch];
195.2664 +            ko.utils.arrayPushAll(eventsToCatch, requestedEventsToCatch);
195.2665 +            eventsToCatch = ko.utils.arrayGetDistinctValues(eventsToCatch);
195.2666 +        }
195.2667 +
195.2668 +        var valueUpdateHandler = function() {
195.2669 +            propertyChangedFired = false;
195.2670 +            var modelValue = valueAccessor();
195.2671 +            var elementValue = ko.selectExtensions.readValue(element);
195.2672 +            ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'value', elementValue);
195.2673 +        }
195.2674 +
195.2675 +        // Workaround for https://github.com/SteveSanderson/knockout/issues/122
195.2676 +        // IE doesn't fire "change" events on textboxes if the user selects a value from its autocomplete list
195.2677 +        var ieAutoCompleteHackNeeded = ko.utils.ieVersion && element.tagName.toLowerCase() == "input" && element.type == "text"
195.2678 +                                       && element.autocomplete != "off" && (!element.form || element.form.autocomplete != "off");
195.2679 +        if (ieAutoCompleteHackNeeded && ko.utils.arrayIndexOf(eventsToCatch, "propertychange") == -1) {
195.2680 +            ko.utils.registerEventHandler(element, "propertychange", function () { propertyChangedFired = true });
195.2681 +            ko.utils.registerEventHandler(element, "blur", function() {
195.2682 +                if (propertyChangedFired) {
195.2683 +                    valueUpdateHandler();
195.2684 +                }
195.2685 +            });
195.2686 +        }
195.2687 +
195.2688 +        ko.utils.arrayForEach(eventsToCatch, function(eventName) {
195.2689 +            // The syntax "after<eventname>" means "run the handler asynchronously after the event"
195.2690 +            // This is useful, for example, to catch "keydown" events after the browser has updated the control
195.2691 +            // (otherwise, ko.selectExtensions.readValue(this) will receive the control's value *before* the key event)
195.2692 +            var handler = valueUpdateHandler;
195.2693 +            if (ko.utils.stringStartsWith(eventName, "after")) {
195.2694 +                handler = function() { setTimeout(valueUpdateHandler, 0) };
195.2695 +                eventName = eventName.substring("after".length);
195.2696 +            }
195.2697 +            ko.utils.registerEventHandler(element, eventName, handler);
195.2698 +        });
195.2699 +    },
195.2700 +    'update': function (element, valueAccessor) {
195.2701 +        var valueIsSelectOption = ko.utils.tagNameLower(element) === "select";
195.2702 +        var newValue = ko.utils.unwrapObservable(valueAccessor());
195.2703 +        var elementValue = ko.selectExtensions.readValue(element);
195.2704 +        var valueHasChanged = (newValue != elementValue);
195.2705 +
195.2706 +        // JavaScript's 0 == "" behavious is unfortunate here as it prevents writing 0 to an empty text box (loose equality suggests the values are the same).
195.2707 +        // We don't want to do a strict equality comparison as that is more confusing for developers in certain cases, so we specifically special case 0 != "" here.
195.2708 +        if ((newValue === 0) && (elementValue !== 0) && (elementValue !== "0"))
195.2709 +            valueHasChanged = true;
195.2710 +
195.2711 +        if (valueHasChanged) {
195.2712 +            var applyValueAction = function () { ko.selectExtensions.writeValue(element, newValue); };
195.2713 +            applyValueAction();
195.2714 +
195.2715 +            // Workaround for IE6 bug: It won't reliably apply values to SELECT nodes during the same execution thread
195.2716 +            // right after you've changed the set of OPTION nodes on it. So for that node type, we'll schedule a second thread
195.2717 +            // to apply the value as well.
195.2718 +            var alsoApplyAsynchronously = valueIsSelectOption;
195.2719 +            if (alsoApplyAsynchronously)
195.2720 +                setTimeout(applyValueAction, 0);
195.2721 +        }
195.2722 +
195.2723 +        // If you try to set a model value that can't be represented in an already-populated dropdown, reject that change,
195.2724 +        // because you're not allowed to have a model value that disagrees with a visible UI selection.
195.2725 +        if (valueIsSelectOption && (element.length > 0))
195.2726 +            ensureDropdownSelectionIsConsistentWithModelValue(element, newValue, /* preferModelValue */ false);
195.2727 +    }
195.2728 +};
195.2729 +ko.bindingHandlers['visible'] = {
195.2730 +    'update': function (element, valueAccessor) {
195.2731 +        var value = ko.utils.unwrapObservable(valueAccessor());
195.2732 +        var isCurrentlyVisible = !(element.style.display == "none");
195.2733 +        if (value && !isCurrentlyVisible)
195.2734 +            element.style.display = "";
195.2735 +        else if ((!value) && isCurrentlyVisible)
195.2736 +            element.style.display = "none";
195.2737 +    }
195.2738 +};
195.2739 +// 'click' is just a shorthand for the usual full-length event:{click:handler}
195.2740 +makeEventHandlerShortcut('click');
195.2741 +// If you want to make a custom template engine,
195.2742 +//
195.2743 +// [1] Inherit from this class (like ko.nativeTemplateEngine does)
195.2744 +// [2] Override 'renderTemplateSource', supplying a function with this signature:
195.2745 +//
195.2746 +//        function (templateSource, bindingContext, options) {
195.2747 +//            // - templateSource.text() is the text of the template you should render
195.2748 +//            // - bindingContext.$data is the data you should pass into the template
195.2749 +//            //   - you might also want to make bindingContext.$parent, bindingContext.$parents,
195.2750 +//            //     and bindingContext.$root available in the template too
195.2751 +//            // - options gives you access to any other properties set on "data-bind: { template: options }"
195.2752 +//            //
195.2753 +//            // Return value: an array of DOM nodes
195.2754 +//        }
195.2755 +//
195.2756 +// [3] Override 'createJavaScriptEvaluatorBlock', supplying a function with this signature:
195.2757 +//
195.2758 +//        function (script) {
195.2759 +//            // Return value: Whatever syntax means "Evaluate the JavaScript statement 'script' and output the result"
195.2760 +//            //               For example, the jquery.tmpl template engine converts 'someScript' to '${ someScript }'
195.2761 +//        }
195.2762 +//
195.2763 +//     This is only necessary if you want to allow data-bind attributes to reference arbitrary template variables.
195.2764 +//     If you don't want to allow that, you can set the property 'allowTemplateRewriting' to false (like ko.nativeTemplateEngine does)
195.2765 +//     and then you don't need to override 'createJavaScriptEvaluatorBlock'.
195.2766 +
195.2767 +ko.templateEngine = function () { };
195.2768 +
195.2769 +ko.templateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
195.2770 +    throw new Error("Override renderTemplateSource");
195.2771 +};
195.2772 +
195.2773 +ko.templateEngine.prototype['createJavaScriptEvaluatorBlock'] = function (script) {
195.2774 +    throw new Error("Override createJavaScriptEvaluatorBlock");
195.2775 +};
195.2776 +
195.2777 +ko.templateEngine.prototype['makeTemplateSource'] = function(template, templateDocument) {
195.2778 +    // Named template
195.2779 +    if (typeof template == "string") {
195.2780 +        templateDocument = templateDocument || document;
195.2781 +        var elem = templateDocument.getElementById(template);
195.2782 +        if (!elem)
195.2783 +            throw new Error("Cannot find template with ID " + template);
195.2784 +        return new ko.templateSources.domElement(elem);
195.2785 +    } else if ((template.nodeType == 1) || (template.nodeType == 8)) {
195.2786 +        // Anonymous template
195.2787 +        return new ko.templateSources.anonymousTemplate(template);
195.2788 +    } else
195.2789 +        throw new Error("Unknown template type: " + template);
195.2790 +};
195.2791 +
195.2792 +ko.templateEngine.prototype['renderTemplate'] = function (template, bindingContext, options, templateDocument) {
195.2793 +    var templateSource = this['makeTemplateSource'](template, templateDocument);
195.2794 +    return this['renderTemplateSource'](templateSource, bindingContext, options);
195.2795 +};
195.2796 +
195.2797 +ko.templateEngine.prototype['isTemplateRewritten'] = function (template, templateDocument) {
195.2798 +    // Skip rewriting if requested
195.2799 +    if (this['allowTemplateRewriting'] === false)
195.2800 +        return true;
195.2801 +    return this['makeTemplateSource'](template, templateDocument)['data']("isRewritten");
195.2802 +};
195.2803 +
195.2804 +ko.templateEngine.prototype['rewriteTemplate'] = function (template, rewriterCallback, templateDocument) {
195.2805 +    var templateSource = this['makeTemplateSource'](template, templateDocument);
195.2806 +    var rewritten = rewriterCallback(templateSource['text']());
195.2807 +    templateSource['text'](rewritten);
195.2808 +    templateSource['data']("isRewritten", true);
195.2809 +};
195.2810 +
195.2811 +ko.exportSymbol('templateEngine', ko.templateEngine);
195.2812 +
195.2813 +ko.templateRewriting = (function () {
195.2814 +    var memoizeDataBindingAttributeSyntaxRegex = /(<[a-z]+\d*(\s+(?!data-bind=)[a-z0-9\-]+(=(\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind=(["'])([\s\S]*?)\5/gi;
195.2815 +    var memoizeVirtualContainerBindingSyntaxRegex = /<!--\s*ko\b\s*([\s\S]*?)\s*-->/g;
195.2816 +
195.2817 +    function validateDataBindValuesForRewriting(keyValueArray) {
195.2818 +        var allValidators = ko.expressionRewriting.bindingRewriteValidators;
195.2819 +        for (var i = 0; i < keyValueArray.length; i++) {
195.2820 +            var key = keyValueArray[i]['key'];
195.2821 +            if (allValidators.hasOwnProperty(key)) {
195.2822 +                var validator = allValidators[key];
195.2823 +
195.2824 +                if (typeof validator === "function") {
195.2825 +                    var possibleErrorMessage = validator(keyValueArray[i]['value']);
195.2826 +                    if (possibleErrorMessage)
195.2827 +                        throw new Error(possibleErrorMessage);
195.2828 +                } else if (!validator) {
195.2829 +                    throw new Error("This template engine does not support the '" + key + "' binding within its templates");
195.2830 +                }
195.2831 +            }
195.2832 +        }
195.2833 +    }
195.2834 +
195.2835 +    function constructMemoizedTagReplacement(dataBindAttributeValue, tagToRetain, templateEngine) {
195.2836 +        var dataBindKeyValueArray = ko.expressionRewriting.parseObjectLiteral(dataBindAttributeValue);
195.2837 +        validateDataBindValuesForRewriting(dataBindKeyValueArray);
195.2838 +        var rewrittenDataBindAttributeValue = ko.expressionRewriting.preProcessBindings(dataBindKeyValueArray);
195.2839 +
195.2840 +        // For no obvious reason, Opera fails to evaluate rewrittenDataBindAttributeValue unless it's wrapped in an additional
195.2841 +        // anonymous function, even though Opera's built-in debugger can evaluate it anyway. No other browser requires this
195.2842 +        // extra indirection.
195.2843 +        var applyBindingsToNextSiblingScript =
195.2844 +            "ko.__tr_ambtns(function($context,$element){return(function(){return{ " + rewrittenDataBindAttributeValue + " } })()})";
195.2845 +        return templateEngine['createJavaScriptEvaluatorBlock'](applyBindingsToNextSiblingScript) + tagToRetain;
195.2846 +    }
195.2847 +
195.2848 +    return {
195.2849 +        ensureTemplateIsRewritten: function (template, templateEngine, templateDocument) {
195.2850 +            if (!templateEngine['isTemplateRewritten'](template, templateDocument))
195.2851 +                templateEngine['rewriteTemplate'](template, function (htmlString) {
195.2852 +                    return ko.templateRewriting.memoizeBindingAttributeSyntax(htmlString, templateEngine);
195.2853 +                }, templateDocument);
195.2854 +        },
195.2855 +
195.2856 +        memoizeBindingAttributeSyntax: function (htmlString, templateEngine) {
195.2857 +            return htmlString.replace(memoizeDataBindingAttributeSyntaxRegex, function () {
195.2858 +                return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[6], /* tagToRetain: */ arguments[1], templateEngine);
195.2859 +            }).replace(memoizeVirtualContainerBindingSyntaxRegex, function() {
195.2860 +                return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[1], /* tagToRetain: */ "<!-- ko -->", templateEngine);
195.2861 +            });
195.2862 +        },
195.2863 +
195.2864 +        applyMemoizedBindingsToNextSibling: function (bindings) {
195.2865 +            return ko.memoization.memoize(function (domNode, bindingContext) {
195.2866 +                if (domNode.nextSibling)
195.2867 +                    ko.applyBindingsToNode(domNode.nextSibling, bindings, bindingContext);
195.2868 +            });
195.2869 +        }
195.2870 +    }
195.2871 +})();
195.2872 +
195.2873 +
195.2874 +// Exported only because it has to be referenced by string lookup from within rewritten template
195.2875 +ko.exportSymbol('__tr_ambtns', ko.templateRewriting.applyMemoizedBindingsToNextSibling);
195.2876 +(function() {
195.2877 +    // A template source represents a read/write way of accessing a template. This is to eliminate the need for template loading/saving
195.2878 +    // logic to be duplicated in every template engine (and means they can all work with anonymous templates, etc.)
195.2879 +    //
195.2880 +    // Two are provided by default:
195.2881 +    //  1. ko.templateSources.domElement       - reads/writes the text content of an arbitrary DOM element
195.2882 +    //  2. ko.templateSources.anonymousElement - uses ko.utils.domData to read/write text *associated* with the DOM element, but
195.2883 +    //                                           without reading/writing the actual element text content, since it will be overwritten
195.2884 +    //                                           with the rendered template output.
195.2885 +    // You can implement your own template source if you want to fetch/store templates somewhere other than in DOM elements.
195.2886 +    // Template sources need to have the following functions:
195.2887 +    //   text() 			- returns the template text from your storage location
195.2888 +    //   text(value)		- writes the supplied template text to your storage location
195.2889 +    //   data(key)			- reads values stored using data(key, value) - see below
195.2890 +    //   data(key, value)	- associates "value" with this template and the key "key". Is used to store information like "isRewritten".
195.2891 +    //
195.2892 +    // Optionally, template sources can also have the following functions:
195.2893 +    //   nodes()            - returns a DOM element containing the nodes of this template, where available
195.2894 +    //   nodes(value)       - writes the given DOM element to your storage location
195.2895 +    // If a DOM element is available for a given template source, template engines are encouraged to use it in preference over text()
195.2896 +    // for improved speed. However, all templateSources must supply text() even if they don't supply nodes().
195.2897 +    //
195.2898 +    // Once you've implemented a templateSource, make your template engine use it by subclassing whatever template engine you were
195.2899 +    // using and overriding "makeTemplateSource" to return an instance of your custom template source.
195.2900 +
195.2901 +    ko.templateSources = {};
195.2902 +
195.2903 +    // ---- ko.templateSources.domElement -----
195.2904 +
195.2905 +    ko.templateSources.domElement = function(element) {
195.2906 +        this.domElement = element;
195.2907 +    }
195.2908 +
195.2909 +    ko.templateSources.domElement.prototype['text'] = function(/* valueToWrite */) {
195.2910 +        var tagNameLower = ko.utils.tagNameLower(this.domElement),
195.2911 +            elemContentsProperty = tagNameLower === "script" ? "text"
195.2912 +                                 : tagNameLower === "textarea" ? "value"
195.2913 +                                 : "innerHTML";
195.2914 +
195.2915 +        if (arguments.length == 0) {
195.2916 +            return this.domElement[elemContentsProperty];
195.2917 +        } else {
195.2918 +            var valueToWrite = arguments[0];
195.2919 +            if (elemContentsProperty === "innerHTML")
195.2920 +                ko.utils.setHtml(this.domElement, valueToWrite);
195.2921 +            else
195.2922 +                this.domElement[elemContentsProperty] = valueToWrite;
195.2923 +        }
195.2924 +    };
195.2925 +
195.2926 +    ko.templateSources.domElement.prototype['data'] = function(key /*, valueToWrite */) {
195.2927 +        if (arguments.length === 1) {
195.2928 +            return ko.utils.domData.get(this.domElement, "templateSourceData_" + key);
195.2929 +        } else {
195.2930 +            ko.utils.domData.set(this.domElement, "templateSourceData_" + key, arguments[1]);
195.2931 +        }
195.2932 +    };
195.2933 +
195.2934 +    // ---- ko.templateSources.anonymousTemplate -----
195.2935 +    // Anonymous templates are normally saved/retrieved as DOM nodes through "nodes".
195.2936 +    // For compatibility, you can also read "text"; it will be serialized from the nodes on demand.
195.2937 +    // Writing to "text" is still supported, but then the template data will not be available as DOM nodes.
195.2938 +
195.2939 +    var anonymousTemplatesDomDataKey = "__ko_anon_template__";
195.2940 +    ko.templateSources.anonymousTemplate = function(element) {
195.2941 +        this.domElement = element;
195.2942 +    }
195.2943 +    ko.templateSources.anonymousTemplate.prototype = new ko.templateSources.domElement();
195.2944 +    ko.templateSources.anonymousTemplate.prototype['text'] = function(/* valueToWrite */) {
195.2945 +        if (arguments.length == 0) {
195.2946 +            var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
195.2947 +            if (templateData.textData === undefined && templateData.containerData)
195.2948 +                templateData.textData = templateData.containerData.innerHTML;
195.2949 +            return templateData.textData;
195.2950 +        } else {
195.2951 +            var valueToWrite = arguments[0];
195.2952 +            ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {textData: valueToWrite});
195.2953 +        }
195.2954 +    };
195.2955 +    ko.templateSources.domElement.prototype['nodes'] = function(/* valueToWrite */) {
195.2956 +        if (arguments.length == 0) {
195.2957 +            var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
195.2958 +            return templateData.containerData;
195.2959 +        } else {
195.2960 +            var valueToWrite = arguments[0];
195.2961 +            ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {containerData: valueToWrite});
195.2962 +        }
195.2963 +    };
195.2964 +
195.2965 +    ko.exportSymbol('templateSources', ko.templateSources);
195.2966 +    ko.exportSymbol('templateSources.domElement', ko.templateSources.domElement);
195.2967 +    ko.exportSymbol('templateSources.anonymousTemplate', ko.templateSources.anonymousTemplate);
195.2968 +})();
195.2969 +(function () {
195.2970 +    var _templateEngine;
195.2971 +    ko.setTemplateEngine = function (templateEngine) {
195.2972 +        if ((templateEngine != undefined) && !(templateEngine instanceof ko.templateEngine))
195.2973 +            throw new Error("templateEngine must inherit from ko.templateEngine");
195.2974 +        _templateEngine = templateEngine;
195.2975 +    }
195.2976 +
195.2977 +    function invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, action) {
195.2978 +        var node, nextInQueue = firstNode, firstOutOfRangeNode = ko.virtualElements.nextSibling(lastNode);
195.2979 +        while (nextInQueue && ((node = nextInQueue) !== firstOutOfRangeNode)) {
195.2980 +            nextInQueue = ko.virtualElements.nextSibling(node);
195.2981 +            if (node.nodeType === 1 || node.nodeType === 8)
195.2982 +                action(node);
195.2983 +        }
195.2984 +    }
195.2985 +
195.2986 +    function activateBindingsOnContinuousNodeArray(continuousNodeArray, bindingContext) {
195.2987 +        // To be used on any nodes that have been rendered by a template and have been inserted into some parent element
195.2988 +        // Walks through continuousNodeArray (which *must* be continuous, i.e., an uninterrupted sequence of sibling nodes, because
195.2989 +        // the algorithm for walking them relies on this), and for each top-level item in the virtual-element sense,
195.2990 +        // (1) Does a regular "applyBindings" to associate bindingContext with this node and to activate any non-memoized bindings
195.2991 +        // (2) Unmemoizes any memos in the DOM subtree (e.g., to activate bindings that had been memoized during template rewriting)
195.2992 +
195.2993 +        if (continuousNodeArray.length) {
195.2994 +            var firstNode = continuousNodeArray[0], lastNode = continuousNodeArray[continuousNodeArray.length - 1];
195.2995 +
195.2996 +            // Need to applyBindings *before* unmemoziation, because unmemoization might introduce extra nodes (that we don't want to re-bind)
195.2997 +            // whereas a regular applyBindings won't introduce new memoized nodes
195.2998 +            invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
195.2999 +                ko.applyBindings(bindingContext, node);
195.3000 +            });
195.3001 +            invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
195.3002 +                ko.memoization.unmemoizeDomNodeAndDescendants(node, [bindingContext]);
195.3003 +            });
195.3004 +        }
195.3005 +    }
195.3006 +
195.3007 +    function getFirstNodeFromPossibleArray(nodeOrNodeArray) {
195.3008 +        return nodeOrNodeArray.nodeType ? nodeOrNodeArray
195.3009 +                                        : nodeOrNodeArray.length > 0 ? nodeOrNodeArray[0]
195.3010 +                                        : null;
195.3011 +    }
195.3012 +
195.3013 +    function executeTemplate(targetNodeOrNodeArray, renderMode, template, bindingContext, options) {
195.3014 +        options = options || {};
195.3015 +        var firstTargetNode = targetNodeOrNodeArray && getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
195.3016 +        var templateDocument = firstTargetNode && firstTargetNode.ownerDocument;
195.3017 +        var templateEngineToUse = (options['templateEngine'] || _templateEngine);
195.3018 +        ko.templateRewriting.ensureTemplateIsRewritten(template, templateEngineToUse, templateDocument);
195.3019 +        var renderedNodesArray = templateEngineToUse['renderTemplate'](template, bindingContext, options, templateDocument);
195.3020 +
195.3021 +        // Loosely check result is an array of DOM nodes
195.3022 +        if ((typeof renderedNodesArray.length != "number") || (renderedNodesArray.length > 0 && typeof renderedNodesArray[0].nodeType != "number"))
195.3023 +            throw new Error("Template engine must return an array of DOM nodes");
195.3024 +
195.3025 +        var haveAddedNodesToParent = false;
195.3026 +        switch (renderMode) {
195.3027 +            case "replaceChildren":
195.3028 +                ko.virtualElements.setDomNodeChildren(targetNodeOrNodeArray, renderedNodesArray);
195.3029 +                haveAddedNodesToParent = true;
195.3030 +                break;
195.3031 +            case "replaceNode":
195.3032 +                ko.utils.replaceDomNodes(targetNodeOrNodeArray, renderedNodesArray);
195.3033 +                haveAddedNodesToParent = true;
195.3034 +                break;
195.3035 +            case "ignoreTargetNode": break;
195.3036 +            default:
195.3037 +                throw new Error("Unknown renderMode: " + renderMode);
195.3038 +        }
195.3039 +
195.3040 +        if (haveAddedNodesToParent) {
195.3041 +            activateBindingsOnContinuousNodeArray(renderedNodesArray, bindingContext);
195.3042 +            if (options['afterRender'])
195.3043 +                ko.dependencyDetection.ignore(options['afterRender'], null, [renderedNodesArray, bindingContext['$data']]);
195.3044 +        }
195.3045 +
195.3046 +        return renderedNodesArray;
195.3047 +    }
195.3048 +
195.3049 +    ko.renderTemplate = function (template, dataOrBindingContext, options, targetNodeOrNodeArray, renderMode) {
195.3050 +        options = options || {};
195.3051 +        if ((options['templateEngine'] || _templateEngine) == undefined)
195.3052 +            throw new Error("Set a template engine before calling renderTemplate");
195.3053 +        renderMode = renderMode || "replaceChildren";
195.3054 +
195.3055 +        if (targetNodeOrNodeArray) {
195.3056 +            var firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
195.3057 +
195.3058 +            var whenToDispose = function () { return (!firstTargetNode) || !ko.utils.domNodeIsAttachedToDocument(firstTargetNode); }; // Passive disposal (on next evaluation)
195.3059 +            var activelyDisposeWhenNodeIsRemoved = (firstTargetNode && renderMode == "replaceNode") ? firstTargetNode.parentNode : firstTargetNode;
195.3060 +
195.3061 +            return ko.dependentObservable( // So the DOM is automatically updated when any dependency changes
195.3062 +                function () {
195.3063 +                    // Ensure we've got a proper binding context to work with
195.3064 +                    var bindingContext = (dataOrBindingContext && (dataOrBindingContext instanceof ko.bindingContext))
195.3065 +                        ? dataOrBindingContext
195.3066 +                        : new ko.bindingContext(ko.utils.unwrapObservable(dataOrBindingContext));
195.3067 +
195.3068 +                    // Support selecting template as a function of the data being rendered
195.3069 +                    var templateName = typeof(template) == 'function' ? template(bindingContext['$data'], bindingContext) : template;
195.3070 +
195.3071 +                    var renderedNodesArray = executeTemplate(targetNodeOrNodeArray, renderMode, templateName, bindingContext, options);
195.3072 +                    if (renderMode == "replaceNode") {
195.3073 +                        targetNodeOrNodeArray = renderedNodesArray;
195.3074 +                        firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
195.3075 +                    }
195.3076 +                },
195.3077 +                null,
195.3078 +                { disposeWhen: whenToDispose, disposeWhenNodeIsRemoved: activelyDisposeWhenNodeIsRemoved }
195.3079 +            );
195.3080 +        } else {
195.3081 +            // We don't yet have a DOM node to evaluate, so use a memo and render the template later when there is a DOM node
195.3082 +            return ko.memoization.memoize(function (domNode) {
195.3083 +                ko.renderTemplate(template, dataOrBindingContext, options, domNode, "replaceNode");
195.3084 +            });
195.3085 +        }
195.3086 +    };
195.3087 +
195.3088 +    ko.renderTemplateForEach = function (template, arrayOrObservableArray, options, targetNode, parentBindingContext) {
195.3089 +        // Since setDomNodeChildrenFromArrayMapping always calls executeTemplateForArrayItem and then
195.3090 +        // activateBindingsCallback for added items, we can store the binding context in the former to use in the latter.
195.3091 +        var arrayItemContext;
195.3092 +
195.3093 +        // This will be called by setDomNodeChildrenFromArrayMapping to get the nodes to add to targetNode
195.3094 +        var executeTemplateForArrayItem = function (arrayValue, index) {
195.3095 +            // Support selecting template as a function of the data being rendered
195.3096 +            arrayItemContext = parentBindingContext['createChildContext'](ko.utils.unwrapObservable(arrayValue), options['as']);
195.3097 +            arrayItemContext['$index'] = index;
195.3098 +            var templateName = typeof(template) == 'function' ? template(arrayValue, arrayItemContext) : template;
195.3099 +            return executeTemplate(null, "ignoreTargetNode", templateName, arrayItemContext, options);
195.3100 +        }
195.3101 +
195.3102 +        // This will be called whenever setDomNodeChildrenFromArrayMapping has added nodes to targetNode
195.3103 +        var activateBindingsCallback = function(arrayValue, addedNodesArray, index) {
195.3104 +            activateBindingsOnContinuousNodeArray(addedNodesArray, arrayItemContext);
195.3105 +            if (options['afterRender'])
195.3106 +                options['afterRender'](addedNodesArray, arrayValue);
195.3107 +        };
195.3108 +
195.3109 +        return ko.dependentObservable(function () {
195.3110 +            var unwrappedArray = ko.utils.unwrapObservable(arrayOrObservableArray) || [];
195.3111 +            if (typeof unwrappedArray.length == "undefined") // Coerce single value into array
195.3112 +                unwrappedArray = [unwrappedArray];
195.3113 +
195.3114 +            // Filter out any entries marked as destroyed
195.3115 +            var filteredArray = ko.utils.arrayFilter(unwrappedArray, function(item) {
195.3116 +                return options['includeDestroyed'] || item === undefined || item === null || !ko.utils.unwrapObservable(item['_destroy']);
195.3117 +            });
195.3118 +
195.3119 +            // Call setDomNodeChildrenFromArrayMapping, ignoring any observables unwrapped within (most likely from a callback function).
195.3120 +            // If the array items are observables, though, they will be unwrapped in executeTemplateForArrayItem and managed within setDomNodeChildrenFromArrayMapping.
195.3121 +            ko.dependencyDetection.ignore(ko.utils.setDomNodeChildrenFromArrayMapping, null, [targetNode, filteredArray, executeTemplateForArrayItem, options, activateBindingsCallback]);
195.3122 +
195.3123 +        }, null, { disposeWhenNodeIsRemoved: targetNode });
195.3124 +    };
195.3125 +
195.3126 +    var templateComputedDomDataKey = '__ko__templateComputedDomDataKey__';
195.3127 +    function disposeOldComputedAndStoreNewOne(element, newComputed) {
195.3128 +        var oldComputed = ko.utils.domData.get(element, templateComputedDomDataKey);
195.3129 +        if (oldComputed && (typeof(oldComputed.dispose) == 'function'))
195.3130 +            oldComputed.dispose();
195.3131 +        ko.utils.domData.set(element, templateComputedDomDataKey, (newComputed && newComputed.isActive()) ? newComputed : undefined);
195.3132 +    }
195.3133 +
195.3134 +    ko.bindingHandlers['template'] = {
195.3135 +        'init': function(element, valueAccessor) {
195.3136 +            // Support anonymous templates
195.3137 +            var bindingValue = ko.utils.unwrapObservable(valueAccessor());
195.3138 +            if ((typeof bindingValue != "string") && (!bindingValue['name']) && (element.nodeType == 1 || element.nodeType == 8)) {
195.3139 +                // It's an anonymous template - store the element contents, then clear the element
195.3140 +                var templateNodes = element.nodeType == 1 ? element.childNodes : ko.virtualElements.childNodes(element),
195.3141 +                    container = ko.utils.moveCleanedNodesToContainerElement(templateNodes); // This also removes the nodes from their current parent
195.3142 +                new ko.templateSources.anonymousTemplate(element)['nodes'](container);
195.3143 +            }
195.3144 +            return { 'controlsDescendantBindings': true };
195.3145 +        },
195.3146 +        'update': function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
195.3147 +            var templateName = ko.utils.unwrapObservable(valueAccessor()),
195.3148 +                options = {},
195.3149 +                shouldDisplay = true,
195.3150 +                dataValue,
195.3151 +                templateComputed = null;
195.3152 +
195.3153 +            if (typeof templateName != "string") {
195.3154 +                options = templateName;
195.3155 +                templateName = options['name'];
195.3156 +
195.3157 +                // Support "if"/"ifnot" conditions
195.3158 +                if ('if' in options)
195.3159 +                    shouldDisplay = ko.utils.unwrapObservable(options['if']);
195.3160 +                if (shouldDisplay && 'ifnot' in options)
195.3161 +                    shouldDisplay = !ko.utils.unwrapObservable(options['ifnot']);
195.3162 +
195.3163 +                dataValue = ko.utils.unwrapObservable(options['data']);
195.3164 +            }
195.3165 +
195.3166 +            if ('foreach' in options) {
195.3167 +                // Render once for each data point (treating data set as empty if shouldDisplay==false)
195.3168 +                var dataArray = (shouldDisplay && options['foreach']) || [];
195.3169 +                templateComputed = ko.renderTemplateForEach(templateName || element, dataArray, options, element, bindingContext);
195.3170 +            } else if (!shouldDisplay) {
195.3171 +                ko.virtualElements.emptyNode(element);
195.3172 +            } else {
195.3173 +                // Render once for this single data point (or use the viewModel if no data was provided)
195.3174 +                var innerBindingContext = ('data' in options) ?
195.3175 +                    bindingContext['createChildContext'](dataValue, options['as']) :  // Given an explitit 'data' value, we create a child binding context for it
195.3176 +                    bindingContext;                                                        // Given no explicit 'data' value, we retain the same binding context
195.3177 +                templateComputed = ko.renderTemplate(templateName || element, innerBindingContext, options, element);
195.3178 +            }
195.3179 +
195.3180 +            // It only makes sense to have a single template computed per element (otherwise which one should have its output displayed?)
195.3181 +            disposeOldComputedAndStoreNewOne(element, templateComputed);
195.3182 +        }
195.3183 +    };
195.3184 +
195.3185 +    // Anonymous templates can't be rewritten. Give a nice error message if you try to do it.
195.3186 +    ko.expressionRewriting.bindingRewriteValidators['template'] = function(bindingValue) {
195.3187 +        var parsedBindingValue = ko.expressionRewriting.parseObjectLiteral(bindingValue);
195.3188 +
195.3189 +        if ((parsedBindingValue.length == 1) && parsedBindingValue[0]['unknown'])
195.3190 +            return null; // It looks like a string literal, not an object literal, so treat it as a named template (which is allowed for rewriting)
195.3191 +
195.3192 +        if (ko.expressionRewriting.keyValueArrayContainsKey(parsedBindingValue, "name"))
195.3193 +            return null; // Named templates can be rewritten, so return "no error"
195.3194 +        return "This template engine does not support anonymous templates nested within its templates";
195.3195 +    };
195.3196 +
195.3197 +    ko.virtualElements.allowedBindings['template'] = true;
195.3198 +})();
195.3199 +
195.3200 +ko.exportSymbol('setTemplateEngine', ko.setTemplateEngine);
195.3201 +ko.exportSymbol('renderTemplate', ko.renderTemplate);
195.3202 +
195.3203 +ko.utils.compareArrays = (function () {
195.3204 +    var statusNotInOld = 'added', statusNotInNew = 'deleted';
195.3205 +
195.3206 +    // Simple calculation based on Levenshtein distance.
195.3207 +    function compareArrays(oldArray, newArray, dontLimitMoves) {
195.3208 +        oldArray = oldArray || [];
195.3209 +        newArray = newArray || [];
195.3210 +
195.3211 +        if (oldArray.length <= newArray.length)
195.3212 +            return compareSmallArrayToBigArray(oldArray, newArray, statusNotInOld, statusNotInNew, dontLimitMoves);
195.3213 +        else
195.3214 +            return compareSmallArrayToBigArray(newArray, oldArray, statusNotInNew, statusNotInOld, dontLimitMoves);
195.3215 +    }
195.3216 +
195.3217 +    function compareSmallArrayToBigArray(smlArray, bigArray, statusNotInSml, statusNotInBig, dontLimitMoves) {
195.3218 +        var myMin = Math.min,
195.3219 +            myMax = Math.max,
195.3220 +            editDistanceMatrix = [],
195.3221 +            smlIndex, smlIndexMax = smlArray.length,
195.3222 +            bigIndex, bigIndexMax = bigArray.length,
195.3223 +            compareRange = (bigIndexMax - smlIndexMax) || 1,
195.3224 +            maxDistance = smlIndexMax + bigIndexMax + 1,
195.3225 +            thisRow, lastRow,
195.3226 +            bigIndexMaxForRow, bigIndexMinForRow;
195.3227 +
195.3228 +        for (smlIndex = 0; smlIndex <= smlIndexMax; smlIndex++) {
195.3229 +            lastRow = thisRow;
195.3230 +            editDistanceMatrix.push(thisRow = []);
195.3231 +            bigIndexMaxForRow = myMin(bigIndexMax, smlIndex + compareRange);
195.3232 +            bigIndexMinForRow = myMax(0, smlIndex - 1);
195.3233 +            for (bigIndex = bigIndexMinForRow; bigIndex <= bigIndexMaxForRow; bigIndex++) {
195.3234 +                if (!bigIndex)
195.3235 +                    thisRow[bigIndex] = smlIndex + 1;
195.3236 +                else if (!smlIndex)  // Top row - transform empty array into new array via additions
195.3237 +                    thisRow[bigIndex] = bigIndex + 1;
195.3238 +                else if (smlArray[smlIndex - 1] === bigArray[bigIndex - 1])
195.3239 +                    thisRow[bigIndex] = lastRow[bigIndex - 1];                  // copy value (no edit)
195.3240 +                else {
195.3241 +                    var northDistance = lastRow[bigIndex] || maxDistance;       // not in big (deletion)
195.3242 +                    var westDistance = thisRow[bigIndex - 1] || maxDistance;    // not in small (addition)
195.3243 +                    thisRow[bigIndex] = myMin(northDistance, westDistance) + 1;
195.3244 +                }
195.3245 +            }
195.3246 +        }
195.3247 +
195.3248 +        var editScript = [], meMinusOne, notInSml = [], notInBig = [];
195.3249 +        for (smlIndex = smlIndexMax, bigIndex = bigIndexMax; smlIndex || bigIndex;) {
195.3250 +            meMinusOne = editDistanceMatrix[smlIndex][bigIndex] - 1;
195.3251 +            if (bigIndex && meMinusOne === editDistanceMatrix[smlIndex][bigIndex-1]) {
195.3252 +                notInSml.push(editScript[editScript.length] = {     // added
195.3253 +                    'status': statusNotInSml,
195.3254 +                    'value': bigArray[--bigIndex],
195.3255 +                    'index': bigIndex });
195.3256 +            } else if (smlIndex && meMinusOne === editDistanceMatrix[smlIndex - 1][bigIndex]) {
195.3257 +                notInBig.push(editScript[editScript.length] = {     // deleted
195.3258 +                    'status': statusNotInBig,
195.3259 +                    'value': smlArray[--smlIndex],
195.3260 +                    'index': smlIndex });
195.3261 +            } else {
195.3262 +                editScript.push({
195.3263 +                    'status': "retained",
195.3264 +                    'value': bigArray[--bigIndex] });
195.3265 +                --smlIndex;
195.3266 +            }
195.3267 +        }
195.3268 +
195.3269 +        if (notInSml.length && notInBig.length) {
195.3270 +            // Set a limit on the number of consecutive non-matching comparisons; having it a multiple of
195.3271 +            // smlIndexMax keeps the time complexity of this algorithm linear.
195.3272 +            var limitFailedCompares = smlIndexMax * 10, failedCompares,
195.3273 +                a, d, notInSmlItem, notInBigItem;
195.3274 +            // Go through the items that have been added and deleted and try to find matches between them.
195.3275 +            for (failedCompares = a = 0; (dontLimitMoves || failedCompares < limitFailedCompares) && (notInSmlItem = notInSml[a]); a++) {
195.3276 +                for (d = 0; notInBigItem = notInBig[d]; d++) {
195.3277 +                    if (notInSmlItem['value'] === notInBigItem['value']) {
195.3278 +                        notInSmlItem['moved'] = notInBigItem['index'];
195.3279 +                        notInBigItem['moved'] = notInSmlItem['index'];
195.3280 +                        notInBig.splice(d,1);       // This item is marked as moved; so remove it from notInBig list
195.3281 +                        failedCompares = d = 0;     // Reset failed compares count because we're checking for consecutive failures
195.3282 +                        break;
195.3283 +                    }
195.3284 +                }
195.3285 +                failedCompares += d;
195.3286 +            }
195.3287 +        }
195.3288 +        return editScript.reverse();
195.3289 +    }
195.3290 +
195.3291 +    return compareArrays;
195.3292 +})();
195.3293 +
195.3294 +ko.exportSymbol('utils.compareArrays', ko.utils.compareArrays);
195.3295 +
195.3296 +(function () {
195.3297 +    // Objective:
195.3298 +    // * Given an input array, a container DOM node, and a function from array elements to arrays of DOM nodes,
195.3299 +    //   map the array elements to arrays of DOM nodes, concatenate together all these arrays, and use them to populate the container DOM node
195.3300 +    // * Next time we're given the same combination of things (with the array possibly having mutated), update the container DOM node
195.3301 +    //   so that its children is again the concatenation of the mappings of the array elements, but don't re-map any array elements that we
195.3302 +    //   previously mapped - retain those nodes, and just insert/delete other ones
195.3303 +
195.3304 +    // "callbackAfterAddingNodes" will be invoked after any "mapping"-generated nodes are inserted into the container node
195.3305 +    // You can use this, for example, to activate bindings on those nodes.
195.3306 +
195.3307 +    function fixUpNodesToBeMovedOrRemoved(contiguousNodeArray) {
195.3308 +        // Before moving, deleting, or replacing a set of nodes that were previously outputted by the "map" function, we have to reconcile
195.3309 +        // them against what is in the DOM right now. It may be that some of the nodes have already been removed from the document,
195.3310 +        // or that new nodes might have been inserted in the middle, for example by a binding. Also, there may previously have been
195.3311 +        // leading comment nodes (created by rewritten string-based templates) that have since been removed during binding.
195.3312 +        // So, this function translates the old "map" output array into its best guess of what set of current DOM nodes should be removed.
195.3313 +        //
195.3314 +        // Rules:
195.3315 +        //   [A] Any leading nodes that aren't in the document any more should be ignored
195.3316 +        //       These most likely correspond to memoization nodes that were already removed during binding
195.3317 +        //       See https://github.com/SteveSanderson/knockout/pull/440
195.3318 +        //   [B] We want to output a contiguous series of nodes that are still in the document. So, ignore any nodes that
195.3319 +        //       have already been removed, and include any nodes that have been inserted among the previous collection
195.3320 +
195.3321 +        // Rule [A]
195.3322 +        while (contiguousNodeArray.length && !ko.utils.domNodeIsAttachedToDocument(contiguousNodeArray[0]))
195.3323 +            contiguousNodeArray.splice(0, 1);
195.3324 +
195.3325 +        // Rule [B]
195.3326 +        if (contiguousNodeArray.length > 1) {
195.3327 +            // Build up the actual new contiguous node set
195.3328 +            var current = contiguousNodeArray[0], last = contiguousNodeArray[contiguousNodeArray.length - 1], newContiguousSet = [current];
195.3329 +            while (current !== last) {
195.3330 +                current = current.nextSibling;
195.3331 +                if (!current) // Won't happen, except if the developer has manually removed some DOM elements (then we're in an undefined scenario)
195.3332 +                    return;
195.3333 +                newContiguousSet.push(current);
195.3334 +            }
195.3335 +
195.3336 +            // ... then mutate the input array to match this.
195.3337 +            // (The following line replaces the contents of contiguousNodeArray with newContiguousSet)
195.3338 +            Array.prototype.splice.apply(contiguousNodeArray, [0, contiguousNodeArray.length].concat(newContiguousSet));
195.3339 +        }
195.3340 +        return contiguousNodeArray;
195.3341 +    }
195.3342 +
195.3343 +    function mapNodeAndRefreshWhenChanged(containerNode, mapping, valueToMap, callbackAfterAddingNodes, index) {
195.3344 +        // Map this array value inside a dependentObservable so we re-map when any dependency changes
195.3345 +        var mappedNodes = [];
195.3346 +        var dependentObservable = ko.dependentObservable(function() {
195.3347 +            var newMappedNodes = mapping(valueToMap, index) || [];
195.3348 +
195.3349 +            // On subsequent evaluations, just replace the previously-inserted DOM nodes
195.3350 +            if (mappedNodes.length > 0) {
195.3351 +                ko.utils.replaceDomNodes(fixUpNodesToBeMovedOrRemoved(mappedNodes), newMappedNodes);
195.3352 +                if (callbackAfterAddingNodes)
195.3353 +                    ko.dependencyDetection.ignore(callbackAfterAddingNodes, null, [valueToMap, newMappedNodes, index]);
195.3354 +            }
195.3355 +
195.3356 +            // Replace the contents of the mappedNodes array, thereby updating the record
195.3357 +            // of which nodes would be deleted if valueToMap was itself later removed
195.3358 +            mappedNodes.splice(0, mappedNodes.length);
195.3359 +            ko.utils.arrayPushAll(mappedNodes, newMappedNodes);
195.3360 +        }, null, { disposeWhenNodeIsRemoved: containerNode, disposeWhen: function() { return (mappedNodes.length == 0) || !ko.utils.domNodeIsAttachedToDocument(mappedNodes[0]) } });
195.3361 +        return { mappedNodes : mappedNodes, dependentObservable : (dependentObservable.isActive() ? dependentObservable : undefined) };
195.3362 +    }
195.3363 +
195.3364 +    var lastMappingResultDomDataKey = "setDomNodeChildrenFromArrayMapping_lastMappingResult";
195.3365 +
195.3366 +    ko.utils.setDomNodeChildrenFromArrayMapping = function (domNode, array, mapping, options, callbackAfterAddingNodes) {
195.3367 +        // Compare the provided array against the previous one
195.3368 +        array = array || [];
195.3369 +        options = options || {};
195.3370 +        var isFirstExecution = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) === undefined;
195.3371 +        var lastMappingResult = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) || [];
195.3372 +        var lastArray = ko.utils.arrayMap(lastMappingResult, function (x) { return x.arrayEntry; });
195.3373 +        var editScript = ko.utils.compareArrays(lastArray, array);
195.3374 +
195.3375 +        // Build the new mapping result
195.3376 +        var newMappingResult = [];
195.3377 +        var lastMappingResultIndex = 0;
195.3378 +        var newMappingResultIndex = 0;
195.3379 +
195.3380 +        var nodesToDelete = [];
195.3381 +        var itemsToProcess = [];
195.3382 +        var itemsForBeforeRemoveCallbacks = [];
195.3383 +        var itemsForMoveCallbacks = [];
195.3384 +        var itemsForAfterAddCallbacks = [];
195.3385 +        var mapData;
195.3386 +
195.3387 +        function itemMovedOrRetained(editScriptIndex, oldPosition) {
195.3388 +            mapData = lastMappingResult[oldPosition];
195.3389 +            if (newMappingResultIndex !== oldPosition)
195.3390 +                itemsForMoveCallbacks[editScriptIndex] = mapData;
195.3391 +            // Since updating the index might change the nodes, do so before calling fixUpNodesToBeMovedOrRemoved
195.3392 +            mapData.indexObservable(newMappingResultIndex++);
195.3393 +            fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes);
195.3394 +            newMappingResult.push(mapData);
195.3395 +            itemsToProcess.push(mapData);
195.3396 +        }
195.3397 +
195.3398 +        function callCallback(callback, items) {
195.3399 +            if (callback) {
195.3400 +                for (var i = 0, n = items.length; i < n; i++) {
195.3401 +                    if (items[i]) {
195.3402 +                        ko.utils.arrayForEach(items[i].mappedNodes, function(node) {
195.3403 +                            callback(node, i, items[i].arrayEntry);
195.3404 +                        });
195.3405 +                    }
195.3406 +                }
195.3407 +            }
195.3408 +        }
195.3409 +
195.3410 +        for (var i = 0, editScriptItem, movedIndex; editScriptItem = editScript[i]; i++) {
195.3411 +            movedIndex = editScriptItem['moved'];
195.3412 +            switch (editScriptItem['status']) {
195.3413 +                case "deleted":
195.3414 +                    if (movedIndex === undefined) {
195.3415 +                        mapData = lastMappingResult[lastMappingResultIndex];
195.3416 +
195.3417 +                        // Stop tracking changes to the mapping for these nodes
195.3418 +                        if (mapData.dependentObservable)
195.3419 +                            mapData.dependentObservable.dispose();
195.3420 +
195.3421 +                        // Queue these nodes for later removal
195.3422 +                        nodesToDelete.push.apply(nodesToDelete, fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes));
195.3423 +                        if (options['beforeRemove']) {
195.3424 +                            itemsForBeforeRemoveCallbacks[i] = mapData;
195.3425 +                            itemsToProcess.push(mapData);
195.3426 +                        }
195.3427 +                    }
195.3428 +                    lastMappingResultIndex++;
195.3429 +                    break;
195.3430 +
195.3431 +                case "retained":
195.3432 +                    itemMovedOrRetained(i, lastMappingResultIndex++);
195.3433 +                    break;
195.3434 +
195.3435 +                case "added":
195.3436 +                    if (movedIndex !== undefined) {
195.3437 +                        itemMovedOrRetained(i, movedIndex);
195.3438 +                    } else {
195.3439 +                        mapData = { arrayEntry: editScriptItem['value'], indexObservable: ko.observable(newMappingResultIndex++) };
195.3440 +                        newMappingResult.push(mapData);
195.3441 +                        itemsToProcess.push(mapData);
195.3442 +                        if (!isFirstExecution)
195.3443 +                            itemsForAfterAddCallbacks[i] = mapData;
195.3444 +                    }
195.3445 +                    break;
195.3446 +            }
195.3447 +        }
195.3448 +
195.3449 +        // Call beforeMove first before any changes have been made to the DOM
195.3450 +        callCallback(options['beforeMove'], itemsForMoveCallbacks);
195.3451 +
195.3452 +        // Next remove nodes for deleted items (or just clean if there's a beforeRemove callback)
195.3453 +        ko.utils.arrayForEach(nodesToDelete, options['beforeRemove'] ? ko.cleanNode : ko.removeNode);
195.3454 +
195.3455 +        // Next add/reorder the remaining items (will include deleted items if there's a beforeRemove callback)
195.3456 +        for (var i = 0, nextNode = ko.virtualElements.firstChild(domNode), lastNode, node; mapData = itemsToProcess[i]; i++) {
195.3457 +            // Get nodes for newly added items
195.3458 +            if (!mapData.mappedNodes)
195.3459 +                ko.utils.extend(mapData, mapNodeAndRefreshWhenChanged(domNode, mapping, mapData.arrayEntry, callbackAfterAddingNodes, mapData.indexObservable));
195.3460 +
195.3461 +            // Put nodes in the right place if they aren't there already
195.3462 +            for (var j = 0; node = mapData.mappedNodes[j]; nextNode = node.nextSibling, lastNode = node, j++) {
195.3463 +                if (node !== nextNode)
195.3464 +                    ko.virtualElements.insertAfter(domNode, node, lastNode);
195.3465 +            }
195.3466 +
195.3467 +            // Run the callbacks for newly added nodes (for example, to apply bindings, etc.)
195.3468 +            if (!mapData.initialized && callbackAfterAddingNodes) {
195.3469 +                callbackAfterAddingNodes(mapData.arrayEntry, mapData.mappedNodes, mapData.indexObservable);
195.3470 +                mapData.initialized = true;
195.3471 +            }
195.3472 +        }
195.3473 +
195.3474 +        // If there's a beforeRemove callback, call it after reordering.
195.3475 +        // Note that we assume that the beforeRemove callback will usually be used to remove the nodes using
195.3476 +        // some sort of animation, which is why we first reorder the nodes that will be removed. If the
195.3477 +        // callback instead removes the nodes right away, it would be more efficient to skip reordering them.
195.3478 +        // Perhaps we'll make that change in the future if this scenario becomes more common.
195.3479 +        callCallback(options['beforeRemove'], itemsForBeforeRemoveCallbacks);
195.3480 +
195.3481 +        // Finally call afterMove and afterAdd callbacks
195.3482 +        callCallback(options['afterMove'], itemsForMoveCallbacks);
195.3483 +        callCallback(options['afterAdd'], itemsForAfterAddCallbacks);
195.3484 +
195.3485 +        // Store a copy of the array items we just considered so we can difference it next time
195.3486 +        ko.utils.domData.set(domNode, lastMappingResultDomDataKey, newMappingResult);
195.3487 +    }
195.3488 +})();
195.3489 +
195.3490 +ko.exportSymbol('utils.setDomNodeChildrenFromArrayMapping', ko.utils.setDomNodeChildrenFromArrayMapping);
195.3491 +ko.nativeTemplateEngine = function () {
195.3492 +    this['allowTemplateRewriting'] = false;
195.3493 +}
195.3494 +
195.3495 +ko.nativeTemplateEngine.prototype = new ko.templateEngine();
195.3496 +ko.nativeTemplateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
195.3497 +    var useNodesIfAvailable = !(ko.utils.ieVersion < 9), // IE<9 cloneNode doesn't work properly
195.3498 +        templateNodesFunc = useNodesIfAvailable ? templateSource['nodes'] : null,
195.3499 +        templateNodes = templateNodesFunc ? templateSource['nodes']() : null;
195.3500 +
195.3501 +    if (templateNodes) {
195.3502 +        return ko.utils.makeArray(templateNodes.cloneNode(true).childNodes);
195.3503 +    } else {
195.3504 +        var templateText = templateSource['text']();
195.3505 +        return ko.utils.parseHtmlFragment(templateText);
195.3506 +    }
195.3507 +};
195.3508 +
195.3509 +ko.nativeTemplateEngine.instance = new ko.nativeTemplateEngine();
195.3510 +ko.setTemplateEngine(ko.nativeTemplateEngine.instance);
195.3511 +
195.3512 +ko.exportSymbol('nativeTemplateEngine', ko.nativeTemplateEngine);
195.3513 +(function() {
195.3514 +    ko.jqueryTmplTemplateEngine = function () {
195.3515 +        // Detect which version of jquery-tmpl you're using. Unfortunately jquery-tmpl
195.3516 +        // doesn't expose a version number, so we have to infer it.
195.3517 +        // Note that as of Knockout 1.3, we only support jQuery.tmpl 1.0.0pre and later,
195.3518 +        // which KO internally refers to as version "2", so older versions are no longer detected.
195.3519 +        var jQueryTmplVersion = this.jQueryTmplVersion = (function() {
195.3520 +            if ((typeof(jQuery) == "undefined") || !(jQuery['tmpl']))
195.3521 +                return 0;
195.3522 +            // Since it exposes no official version number, we use our own numbering system. To be updated as jquery-tmpl evolves.
195.3523 +            try {
195.3524 +                if (jQuery['tmpl']['tag']['tmpl']['open'].toString().indexOf('__') >= 0) {
195.3525 +                    // Since 1.0.0pre, custom tags should append markup to an array called "__"
195.3526 +                    return 2; // Final version of jquery.tmpl
195.3527 +                }
195.3528 +            } catch(ex) { /* Apparently not the version we were looking for */ }
195.3529 +
195.3530 +            return 1; // Any older version that we don't support
195.3531 +        })();
195.3532 +
195.3533 +        function ensureHasReferencedJQueryTemplates() {
195.3534 +            if (jQueryTmplVersion < 2)
195.3535 +                throw new Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");
195.3536 +        }
195.3537 +
195.3538 +        function executeTemplate(compiledTemplate, data, jQueryTemplateOptions) {
195.3539 +            return jQuery['tmpl'](compiledTemplate, data, jQueryTemplateOptions);
195.3540 +        }
195.3541 +
195.3542 +        this['renderTemplateSource'] = function(templateSource, bindingContext, options) {
195.3543 +            options = options || {};
195.3544 +            ensureHasReferencedJQueryTemplates();
195.3545 +
195.3546 +            // Ensure we have stored a precompiled version of this template (don't want to reparse on every render)
195.3547 +            var precompiled = templateSource['data']('precompiled');
195.3548 +            if (!precompiled) {
195.3549 +                var templateText = templateSource['text']() || "";
195.3550 +                // Wrap in "with($whatever.koBindingContext) { ... }"
195.3551 +                templateText = "{{ko_with $item.koBindingContext}}" + templateText + "{{/ko_with}}";
195.3552 +
195.3553 +                precompiled = jQuery['template'](null, templateText);
195.3554 +                templateSource['data']('precompiled', precompiled);
195.3555 +            }
195.3556 +
195.3557 +            var data = [bindingContext['$data']]; // Prewrap the data in an array to stop jquery.tmpl from trying to unwrap any arrays
195.3558 +            var jQueryTemplateOptions = jQuery['extend']({ 'koBindingContext': bindingContext }, options['templateOptions']);
195.3559 +
195.3560 +            var resultNodes = executeTemplate(precompiled, data, jQueryTemplateOptions);
195.3561 +            resultNodes['appendTo'](document.createElement("div")); // Using "appendTo" forces jQuery/jQuery.tmpl to perform necessary cleanup work
195.3562 +
195.3563 +            jQuery['fragments'] = {}; // Clear jQuery's fragment cache to avoid a memory leak after a large number of template renders
195.3564 +            return resultNodes;
195.3565 +        };
195.3566 +
195.3567 +        this['createJavaScriptEvaluatorBlock'] = function(script) {
195.3568 +            return "{{ko_code ((function() { return " + script + " })()) }}";
195.3569 +        };
195.3570 +
195.3571 +        this['addTemplate'] = function(templateName, templateMarkup) {
195.3572 +            document.write("<script type='text/html' id='" + templateName + "'>" + templateMarkup + "</script>");
195.3573 +        };
195.3574 +
195.3575 +        if (jQueryTmplVersion > 0) {
195.3576 +            jQuery['tmpl']['tag']['ko_code'] = {
195.3577 +                open: "__.push($1 || '');"
195.3578 +            };
195.3579 +            jQuery['tmpl']['tag']['ko_with'] = {
195.3580 +                open: "with($1) {",
195.3581 +                close: "} "
195.3582 +            };
195.3583 +        }
195.3584 +    };
195.3585 +
195.3586 +    ko.jqueryTmplTemplateEngine.prototype = new ko.templateEngine();
195.3587 +
195.3588 +    // Use this one by default *only if jquery.tmpl is referenced*
195.3589 +    var jqueryTmplTemplateEngineInstance = new ko.jqueryTmplTemplateEngine();
195.3590 +    if (jqueryTmplTemplateEngineInstance.jQueryTmplVersion > 0)
195.3591 +        ko.setTemplateEngine(jqueryTmplTemplateEngineInstance);
195.3592 +
195.3593 +    ko.exportSymbol('jqueryTmplTemplateEngine', ko.jqueryTmplTemplateEngine);
195.3594 +})();
195.3595 +});
195.3596 +})(window,document,navigator,window["jQuery"]);
195.3597 +})();
195.3598 \ No newline at end of file
   196.1 --- a/ko-fx/src/test/java/org/apidesign/html/kofx/DynamicHTTP.java	Thu Dec 19 17:11:01 2013 +0100
   196.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   196.3 @@ -1,237 +0,0 @@
   196.4 -/**
   196.5 - * HTML via Java(tm) Language Bindings
   196.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   196.7 - *
   196.8 - * This program is free software: you can redistribute it and/or modify
   196.9 - * it under the terms of the GNU General Public License as published by
  196.10 - * the Free Software Foundation, version 2 of the License.
  196.11 - *
  196.12 - * This program is distributed in the hope that it will be useful,
  196.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  196.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  196.15 - * GNU General Public License for more details. apidesign.org
  196.16 - * designates this particular file as subject to the
  196.17 - * "Classpath" exception as provided by apidesign.org
  196.18 - * in the License file that accompanied this code.
  196.19 - *
  196.20 - * You should have received a copy of the GNU General Public License
  196.21 - * along with this program. Look for COPYING file in the top folder.
  196.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  196.23 - */
  196.24 -package org.apidesign.html.kofx;
  196.25 -
  196.26 -import java.io.ByteArrayInputStream;
  196.27 -import java.io.ByteArrayOutputStream;
  196.28 -import java.io.IOException;
  196.29 -import java.io.InputStream;
  196.30 -import java.io.OutputStream;
  196.31 -import java.io.Reader;
  196.32 -import java.net.URI;
  196.33 -import java.net.URISyntaxException;
  196.34 -import java.util.ArrayList;
  196.35 -import java.util.List;
  196.36 -import java.util.logging.Level;
  196.37 -import java.util.logging.Logger;
  196.38 -import org.glassfish.grizzly.PortRange;
  196.39 -import org.glassfish.grizzly.http.server.HttpHandler;
  196.40 -import org.glassfish.grizzly.http.server.HttpServer;
  196.41 -import org.glassfish.grizzly.http.server.NetworkListener;
  196.42 -import org.glassfish.grizzly.http.server.Request;
  196.43 -import org.glassfish.grizzly.http.server.Response;
  196.44 -import org.glassfish.grizzly.http.server.ServerConfiguration;
  196.45 -import org.glassfish.grizzly.websockets.WebSocket;
  196.46 -import org.glassfish.grizzly.websockets.WebSocketAddOn;
  196.47 -import org.glassfish.grizzly.websockets.WebSocketApplication;
  196.48 -import org.glassfish.grizzly.websockets.WebSocketEngine;
  196.49 -
  196.50 -/**
  196.51 - *
  196.52 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  196.53 - */
  196.54 -final class DynamicHTTP extends HttpHandler {
  196.55 -    private static final Logger LOG = Logger.getLogger(DynamicHTTP.class.getName());
  196.56 -    private static int resourcesCount;
  196.57 -    private static List<Resource> resources;
  196.58 -    private static ServerConfiguration conf;
  196.59 -    private static HttpServer server;
  196.60 -    
  196.61 -    private DynamicHTTP() {
  196.62 -    }
  196.63 -    
  196.64 -    static URI initServer() throws Exception {
  196.65 -        server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
  196.66 -        final WebSocketAddOn addon = new WebSocketAddOn();
  196.67 -        for (NetworkListener listener : server.getListeners()) {
  196.68 -            listener.registerAddOn(addon);
  196.69 -        }        
  196.70 -        resources = new ArrayList<Resource>();
  196.71 -
  196.72 -        conf = server.getServerConfiguration();
  196.73 -        final DynamicHTTP dh = new DynamicHTTP();
  196.74 -
  196.75 -        conf.addHttpHandler(dh, "/");
  196.76 -        
  196.77 -        server.start();
  196.78 -
  196.79 -        return pageURL("http", server, "/test.html");
  196.80 -    }
  196.81 -    
  196.82 -    @Override
  196.83 -    public void service(Request request, Response response) throws Exception {
  196.84 -        if ("/test.html".equals(request.getRequestURI())) {
  196.85 -            response.setContentType("text/html");
  196.86 -            final InputStream is = DynamicHTTP.class.getResourceAsStream("test.html");
  196.87 -            copyStream(is, response.getOutputStream(), null);
  196.88 -            return;
  196.89 -        }
  196.90 -        if ("/dynamic".equals(request.getRequestURI())) {
  196.91 -            String mimeType = request.getParameter("mimeType");
  196.92 -            List<String> params = new ArrayList<String>();
  196.93 -            boolean webSocket = false;
  196.94 -            for (int i = 0;; i++) {
  196.95 -                String p = request.getParameter("param" + i);
  196.96 -                if (p == null) {
  196.97 -                    break;
  196.98 -                }
  196.99 -                if ("protocol:ws".equals(p)) {
 196.100 -                    webSocket = true;
 196.101 -                    continue;
 196.102 -                }
 196.103 -                params.add(p);
 196.104 -            }
 196.105 -            final String cnt = request.getParameter("content");
 196.106 -            String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
 196.107 -            ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
 196.108 -            URI url;
 196.109 -            final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
 196.110 -            if (webSocket) {
 196.111 -                url = registerWebSocket(res);
 196.112 -            } else {
 196.113 -                url = registerResource(res);
 196.114 -            }
 196.115 -            response.getWriter().write(url.toString());
 196.116 -            response.getWriter().write("\n");
 196.117 -            return;
 196.118 -        }
 196.119 -
 196.120 -        for (Resource r : resources) {
 196.121 -            if (r.httpPath.equals(request.getRequestURI())) {
 196.122 -                response.setContentType(r.httpType);
 196.123 -                r.httpContent.reset();
 196.124 -                String[] params = null;
 196.125 -                if (r.parameters.length != 0) {
 196.126 -                    params = new String[r.parameters.length];
 196.127 -                    for (int i = 0; i < r.parameters.length; i++) {
 196.128 -                        params[i] = request.getParameter(r.parameters[i]);
 196.129 -                        if (params[i] == null) {
 196.130 -                            if ("http.method".equals(r.parameters[i])) {
 196.131 -                                params[i] = request.getMethod().toString();
 196.132 -                            } else if ("http.requestBody".equals(r.parameters[i])) {
 196.133 -                                Reader rdr = request.getReader();
 196.134 -                                StringBuilder sb = new StringBuilder();
 196.135 -                                for (;;) {
 196.136 -                                    int ch = rdr.read();
 196.137 -                                    if (ch == -1) {
 196.138 -                                        break;
 196.139 -                                    }
 196.140 -                                    sb.append((char) ch);
 196.141 -                                }
 196.142 -                                params[i] = sb.toString();
 196.143 -                            }
 196.144 -                        }
 196.145 -                        if (params[i] == null) {
 196.146 -                            params[i] = "null";
 196.147 -                        }
 196.148 -                    }
 196.149 -                }
 196.150 -
 196.151 -                copyStream(r.httpContent, response.getOutputStream(), null, params);
 196.152 -            }
 196.153 -        }
 196.154 -    }
 196.155 -    
 196.156 -    private URI registerWebSocket(Resource r) {
 196.157 -        WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
 196.158 -        return pageURL("ws", server, r.httpPath);
 196.159 -    }
 196.160 -
 196.161 -    private URI registerResource(Resource r) {
 196.162 -        if (!resources.contains(r)) {
 196.163 -            resources.add(r);
 196.164 -            conf.addHttpHandler(this, r.httpPath);
 196.165 -        }
 196.166 -        return pageURL("http", server, r.httpPath);
 196.167 -    }
 196.168 -    
 196.169 -    private static URI pageURL(String proto, HttpServer server, final String page) {
 196.170 -        NetworkListener listener = server.getListeners().iterator().next();
 196.171 -        int port = listener.getPort();
 196.172 -        try {
 196.173 -            return new URI(proto + "://localhost:" + port + page);
 196.174 -        } catch (URISyntaxException ex) {
 196.175 -            throw new IllegalStateException(ex);
 196.176 -        }
 196.177 -    }
 196.178 -    
 196.179 -    static final class Resource {
 196.180 -
 196.181 -        final InputStream httpContent;
 196.182 -        final String httpType;
 196.183 -        final String httpPath;
 196.184 -        final String[] parameters;
 196.185 -
 196.186 -        Resource(InputStream httpContent, String httpType, String httpPath,
 196.187 -            String[] parameters) {
 196.188 -            httpContent.mark(Integer.MAX_VALUE);
 196.189 -            this.httpContent = httpContent;
 196.190 -            this.httpType = httpType;
 196.191 -            this.httpPath = httpPath;
 196.192 -            this.parameters = parameters;
 196.193 -        }
 196.194 -    }
 196.195 -
 196.196 -    static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
 196.197 -        for (;;) {
 196.198 -            int ch = is.read();
 196.199 -            if (ch == -1) {
 196.200 -                break;
 196.201 -            }
 196.202 -            if (ch == '$' && params.length > 0) {
 196.203 -                int cnt = is.read() - '0';
 196.204 -                if (baseURL != null && cnt == 'U' - '0') {
 196.205 -                    os.write(baseURL.getBytes("UTF-8"));
 196.206 -                } else {
 196.207 -                    if (cnt >= 0 && cnt < params.length) {
 196.208 -                        os.write(params[cnt].getBytes("UTF-8"));
 196.209 -                    } else {
 196.210 -                        os.write('$');
 196.211 -                        os.write(cnt + '0');
 196.212 -                    }
 196.213 -                }
 196.214 -            } else {
 196.215 -                os.write(ch);
 196.216 -            }
 196.217 -        }
 196.218 -    }
 196.219 -    
 196.220 -    private static class WS extends WebSocketApplication {
 196.221 -        private final Resource r;
 196.222 -
 196.223 -        private WS(Resource r) {
 196.224 -            this.r = r;
 196.225 -        }
 196.226 -
 196.227 -        @Override
 196.228 -        public void onMessage(WebSocket socket, String text) {
 196.229 -            try {
 196.230 -                r.httpContent.reset();
 196.231 -                ByteArrayOutputStream out = new ByteArrayOutputStream();
 196.232 -                copyStream(r.httpContent, out, null, text);
 196.233 -                String s = new String(out.toByteArray(), "UTF-8");
 196.234 -                socket.send(s);
 196.235 -            } catch (IOException ex) {
 196.236 -                LOG.log(Level.WARNING, "Error processing message " + text, ex);
 196.237 -            }
 196.238 -        }
 196.239 -    }
 196.240 -}
   197.1 --- a/ko-fx/src/test/java/org/apidesign/html/kofx/KOFx.java	Thu Dec 19 17:11:01 2013 +0100
   197.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   197.3 @@ -1,96 +0,0 @@
   197.4 -/**
   197.5 - * HTML via Java(tm) Language Bindings
   197.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   197.7 - *
   197.8 - * This program is free software: you can redistribute it and/or modify
   197.9 - * it under the terms of the GNU General Public License as published by
  197.10 - * the Free Software Foundation, version 2 of the License.
  197.11 - *
  197.12 - * This program is distributed in the hope that it will be useful,
  197.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  197.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  197.15 - * GNU General Public License for more details. apidesign.org
  197.16 - * designates this particular file as subject to the
  197.17 - * "Classpath" exception as provided by apidesign.org
  197.18 - * in the License file that accompanied this code.
  197.19 - *
  197.20 - * You should have received a copy of the GNU General Public License
  197.21 - * along with this program. Look for COPYING file in the top folder.
  197.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  197.23 - */
  197.24 -package org.apidesign.html.kofx;
  197.25 -
  197.26 -import java.io.Closeable;
  197.27 -import java.lang.reflect.InvocationTargetException;
  197.28 -import java.lang.reflect.Method;
  197.29 -import javafx.application.Platform;
  197.30 -import org.apidesign.html.boot.spi.Fn;
  197.31 -import org.testng.ITest;
  197.32 -import org.testng.annotations.Test;
  197.33 -
  197.34 -/**
  197.35 - *
  197.36 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  197.37 - */
  197.38 -public final class KOFx implements ITest, Runnable {
  197.39 -    private final Fn.Presenter p;
  197.40 -    private final Method m;
  197.41 -    private Object result;
  197.42 -    private Object inst;
  197.43 -    private int count;
  197.44 -
  197.45 -    KOFx(Fn.Presenter p, Method m) {
  197.46 -        this.p = p;
  197.47 -        this.m = m;
  197.48 -    }
  197.49 -
  197.50 -    @Override
  197.51 -    public String getTestName() {
  197.52 -        return m.getName();
  197.53 -    }
  197.54 -
  197.55 -    @Test
  197.56 -    public synchronized void executeTest() throws Exception {
  197.57 -        if (result == null) {
  197.58 -            Platform.runLater(this);
  197.59 -            wait();
  197.60 -        }
  197.61 -        if (result instanceof Exception) {
  197.62 -            throw (Exception)result;
  197.63 -        }
  197.64 -        if (result instanceof Error) {
  197.65 -            throw (Error)result;
  197.66 -        }
  197.67 -    }
  197.68 -
  197.69 -    @Override
  197.70 -    public synchronized void run() {
  197.71 -        boolean notify = true;
  197.72 -        try (Closeable a = Fn.activate(p)) {
  197.73 -            if (inst == null) {
  197.74 -                inst = m.getDeclaringClass().newInstance();
  197.75 -            }
  197.76 -            result = m.invoke(inst);
  197.77 -            if (result == null) {
  197.78 -                result = this;
  197.79 -            }
  197.80 -        } catch (InvocationTargetException ex) {
  197.81 -            Throwable r = ex.getTargetException();
  197.82 -            if (r instanceof InterruptedException) {
  197.83 -                if (count++ < 10000) {
  197.84 -                    notify = false;
  197.85 -                    Platform.runLater(this);
  197.86 -                    return;
  197.87 -                }
  197.88 -            }
  197.89 -            result = r;
  197.90 -        } catch (Exception ex) {
  197.91 -            result = ex;
  197.92 -        } finally {
  197.93 -            if (notify) {
  197.94 -                notifyAll();
  197.95 -            }
  197.96 -        }
  197.97 -    }
  197.98 -    
  197.99 -}
   198.1 --- a/ko-fx/src/test/java/org/apidesign/html/kofx/KnockoutFXTest.java	Thu Dec 19 17:11:01 2013 +0100
   198.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   198.3 @@ -1,207 +0,0 @@
   198.4 -/**
   198.5 - * HTML via Java(tm) Language Bindings
   198.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   198.7 - *
   198.8 - * This program is free software: you can redistribute it and/or modify
   198.9 - * it under the terms of the GNU General Public License as published by
  198.10 - * the Free Software Foundation, version 2 of the License.
  198.11 - *
  198.12 - * This program is distributed in the hope that it will be useful,
  198.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  198.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  198.15 - * GNU General Public License for more details. apidesign.org
  198.16 - * designates this particular file as subject to the
  198.17 - * "Classpath" exception as provided by apidesign.org
  198.18 - * in the License file that accompanied this code.
  198.19 - *
  198.20 - * You should have received a copy of the GNU General Public License
  198.21 - * along with this program. Look for COPYING file in the top folder.
  198.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  198.23 - */
  198.24 -package org.apidesign.html.kofx;
  198.25 -
  198.26 -import java.io.BufferedReader;
  198.27 -import java.io.IOException;
  198.28 -import java.io.InputStreamReader;
  198.29 -import java.lang.annotation.Annotation;
  198.30 -import java.lang.reflect.Method;
  198.31 -import java.net.URI;
  198.32 -import java.net.URISyntaxException;
  198.33 -import java.net.URL;
  198.34 -import java.net.URLConnection;
  198.35 -import java.util.ArrayList;
  198.36 -import java.util.List;
  198.37 -import java.util.Map;
  198.38 -import java.util.concurrent.Executors;
  198.39 -import net.java.html.BrwsrCtx;
  198.40 -import net.java.html.boot.BrowserBuilder;
  198.41 -import net.java.html.js.JavaScriptBody;
  198.42 -import org.apidesign.html.boot.impl.FnContext;
  198.43 -import org.apidesign.html.boot.spi.Fn;
  198.44 -import org.apidesign.html.context.spi.Contexts;
  198.45 -import org.apidesign.html.json.spi.Technology;
  198.46 -import org.apidesign.html.json.spi.Transfer;
  198.47 -import org.apidesign.html.json.spi.WSTransfer;
  198.48 -import org.apidesign.html.json.tck.KOTest;
  198.49 -import org.apidesign.html.json.tck.KnockoutTCK;
  198.50 -import org.json.JSONException;
  198.51 -import org.json.JSONObject;
  198.52 -import org.openide.util.lookup.ServiceProvider;
  198.53 -import org.testng.annotations.Factory;
  198.54 -import static org.testng.Assert.*;
  198.55 -
  198.56 -/**
  198.57 - *
  198.58 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  198.59 - */
  198.60 -@ServiceProvider(service = KnockoutTCK.class)
  198.61 -public final class KnockoutFXTest extends KnockoutTCK {
  198.62 -    private static Class<?> browserClass;
  198.63 -    private static Fn.Presenter browserContext;
  198.64 -    
  198.65 -    public KnockoutFXTest() {
  198.66 -    }
  198.67 -    
  198.68 -    @Factory public static Object[] compatibilityTests() throws Exception {
  198.69 -        Class[] arr = testClasses();
  198.70 -        for (int i = 0; i < arr.length; i++) {
  198.71 -            assertEquals(
  198.72 -                arr[i].getClassLoader(),
  198.73 -                KnockoutFXTest.class.getClassLoader(),
  198.74 -                "All classes loaded by the same classloader"
  198.75 -            );
  198.76 -        }
  198.77 -        
  198.78 -        URI uri = DynamicHTTP.initServer();
  198.79 -    
  198.80 -        final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(KnockoutFXTest.class).
  198.81 -            loadPage(uri.toString()).
  198.82 -            invoke("initialized");
  198.83 -        
  198.84 -        Executors.newSingleThreadExecutor().submit(new Runnable() {
  198.85 -            @Override
  198.86 -            public void run() {
  198.87 -                bb.showAndWait();
  198.88 -            }
  198.89 -        });
  198.90 -        
  198.91 -        ClassLoader l = getClassLoader();
  198.92 -        List<Object> res = new ArrayList<Object>();
  198.93 -        for (int i = 0; i < arr.length; i++) {
  198.94 -            Class<?> c = Class.forName(arr[i].getName(), true, l);
  198.95 -            seekKOTests(c, res);
  198.96 -        }
  198.97 -        Class<?> c = Class.forName(LessCallbacksCheck.class.getName(), true, l);
  198.98 -        seekKOTests(c, res);
  198.99 -        return res.toArray();
 198.100 -    }
 198.101 -
 198.102 -    private static void seekKOTests(Class<?> c, List<Object> res) throws SecurityException, ClassNotFoundException {
 198.103 -        Class<? extends Annotation> koTest =
 198.104 -            c.getClassLoader().loadClass(KOTest.class.getName()).
 198.105 -            asSubclass(Annotation.class);
 198.106 -        for (Method m : c.getMethods()) {
 198.107 -            if (m.getAnnotation(koTest) != null) {
 198.108 -                res.add(new KOFx(browserContext, m));
 198.109 -            }
 198.110 -        }
 198.111 -    }
 198.112 -
 198.113 -    static synchronized ClassLoader getClassLoader() throws InterruptedException {
 198.114 -        while (browserClass == null) {
 198.115 -            KnockoutFXTest.class.wait();
 198.116 -        }
 198.117 -        return browserClass.getClassLoader();
 198.118 -    }
 198.119 -    
 198.120 -    public static synchronized void initialized(Class<?> browserCls) throws Exception {
 198.121 -        browserClass = browserCls;
 198.122 -        browserContext = Fn.activePresenter();
 198.123 -        KnockoutFXTest.class.notifyAll();
 198.124 -    }
 198.125 -    
 198.126 -    public static void initialized() throws Exception {
 198.127 -        Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(KnockoutFXTest.class.getName());
 198.128 -        Method m = classpathClass.getMethod("initialized", Class.class);
 198.129 -        m.invoke(null, KnockoutFXTest.class);
 198.130 -        browserContext = Fn.activePresenter();
 198.131 -    }
 198.132 -    
 198.133 -    @Override
 198.134 -    public BrwsrCtx createContext() {
 198.135 -        FXContext fx = new FXContext(browserContext);
 198.136 -        Contexts.Builder cb = Contexts.newBuilder().
 198.137 -            register(Technology.class, fx, 10).
 198.138 -            register(Transfer.class, fx, 10);
 198.139 -        if (fx.areWebSocketsSupported()) {
 198.140 -            cb.register(WSTransfer.class, fx, 10);
 198.141 -        }
 198.142 -        return cb.build();
 198.143 -    }
 198.144 -
 198.145 -    @Override
 198.146 -    public Object createJSON(Map<String, Object> values) {
 198.147 -        JSONObject json = new JSONObject();
 198.148 -        for (Map.Entry<String, Object> entry : values.entrySet()) {
 198.149 -            try {
 198.150 -                json.put(entry.getKey(), entry.getValue());
 198.151 -            } catch (JSONException ex) {
 198.152 -                throw new IllegalStateException(ex);
 198.153 -            }
 198.154 -        }
 198.155 -        return json;
 198.156 -    }
 198.157 -
 198.158 -    @Override
 198.159 -    @JavaScriptBody(args = { "s", "args" }, body = ""
 198.160 -        + "var f = new Function(s); "
 198.161 -        + "return f.apply(null, args);"
 198.162 -    )
 198.163 -    public native Object executeScript(String script, Object[] arguments);
 198.164 -
 198.165 -    @JavaScriptBody(args = {  }, body = 
 198.166 -          "var h;"
 198.167 -        + "if (!!window && !!window.location && !!window.location.href)\n"
 198.168 -        + "  h = window.location.href;\n"
 198.169 -        + "else "
 198.170 -        + "  h = null;"
 198.171 -        + "return h;\n"
 198.172 -    )
 198.173 -    private static native String findBaseURL();
 198.174 -    
 198.175 -    @Override
 198.176 -    public URI prepareURL(String content, String mimeType, String[] parameters) {
 198.177 -        try {
 198.178 -            final URL baseURL = new URL(findBaseURL());
 198.179 -            StringBuilder sb = new StringBuilder();
 198.180 -            sb.append("/dynamic?mimeType=").append(mimeType);
 198.181 -            for (int i = 0; i < parameters.length; i++) {
 198.182 -                sb.append("&param" + i).append("=").append(parameters[i]);
 198.183 -            }
 198.184 -            String mangle = content.replace("\n", "%0a")
 198.185 -                .replace("\"", "\\\"").replace(" ", "%20");
 198.186 -            sb.append("&content=").append(mangle);
 198.187 -
 198.188 -            URL query = new URL(baseURL, sb.toString());
 198.189 -            URLConnection c = query.openConnection();
 198.190 -            BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
 198.191 -            URI connectTo = new URI(br.readLine());
 198.192 -            return connectTo;
 198.193 -        } catch (IOException ex) {
 198.194 -            throw new IllegalStateException(ex);
 198.195 -        } catch (URISyntaxException ex) {
 198.196 -            throw new IllegalStateException(ex);
 198.197 -        }
 198.198 -    }
 198.199 -
 198.200 -    @Override
 198.201 -    public boolean canFailWebSocketTest() {
 198.202 -        try {
 198.203 -            Class.forName("java.util.function.Function");
 198.204 -            return false;
 198.205 -        } catch (ClassNotFoundException ex) {
 198.206 -            // running on JDK7, FX WebView WebSocket impl does not work
 198.207 -            return true;
 198.208 -        }
 198.209 -    }
 198.210 -}
   199.1 --- a/ko-fx/src/test/java/org/apidesign/html/kofx/LessCallbacksCheck.java	Thu Dec 19 17:11:01 2013 +0100
   199.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   199.3 @@ -1,60 +0,0 @@
   199.4 -/**
   199.5 - * HTML via Java(tm) Language Bindings
   199.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   199.7 - *
   199.8 - * This program is free software: you can redistribute it and/or modify
   199.9 - * it under the terms of the GNU General Public License as published by
  199.10 - * the Free Software Foundation, version 2 of the License.
  199.11 - *
  199.12 - * This program is distributed in the hope that it will be useful,
  199.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  199.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  199.15 - * GNU General Public License for more details. apidesign.org
  199.16 - * designates this particular file as subject to the
  199.17 - * "Classpath" exception as provided by apidesign.org
  199.18 - * in the License file that accompanied this code.
  199.19 - *
  199.20 - * You should have received a copy of the GNU General Public License
  199.21 - * along with this program. Look for COPYING file in the top folder.
  199.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  199.23 - */
  199.24 -package org.apidesign.html.kofx;
  199.25 -
  199.26 -import java.io.PrintWriter;
  199.27 -import java.io.StringWriter;
  199.28 -import net.java.html.json.ComputedProperty;
  199.29 -import net.java.html.json.Model;
  199.30 -import net.java.html.json.Property;
  199.31 -import org.apidesign.html.json.tck.KOTest;
  199.32 -
  199.33 -/**
  199.34 - *
  199.35 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  199.36 - */
  199.37 -@Model(className = "LessCalls", properties = {
  199.38 -    @Property(name = "value", type = int.class)
  199.39 -})
  199.40 -public class LessCallbacksCheck {
  199.41 -    private static StringWriter sw;
  199.42 -    
  199.43 -    @ComputedProperty static int plusOne(int value) {
  199.44 -        if (sw == null) {
  199.45 -            sw = new StringWriter();
  199.46 -        }
  199.47 -        new Exception("Who calls me?").printStackTrace(
  199.48 -            new PrintWriter(sw)
  199.49 -        );
  199.50 -        return value + 1;
  199.51 -    }
  199.52 -    
  199.53 -    @KOTest public void dontCallForInitialValueBackToJavaVM() {
  199.54 -        LessCalls m = new LessCalls(10).applyBindings();
  199.55 -        assert m.getPlusOne() == 11 : "Expecting 11: " + m.getPlusOne();
  199.56 -        
  199.57 -        assert sw != null : "StringWriter should be initialized: " + sw;
  199.58 -        
  199.59 -        if (sw.toString().contains("$JsCallbacks$")) {
  199.60 -            assert false : "Don't call for initial value via JsCallbacks:\n" + sw;
  199.61 -        }
  199.62 -    }
  199.63 -}
   200.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   200.2 +++ b/ko-fx/src/test/java/org/netbeans/html/kofx/DynamicHTTP.java	Tue Jan 07 08:21:57 2014 +0100
   200.3 @@ -0,0 +1,259 @@
   200.4 +/**
   200.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   200.6 + *
   200.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   200.8 + *
   200.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  200.10 + * Other names may be trademarks of their respective owners.
  200.11 + *
  200.12 + * The contents of this file are subject to the terms of either the GNU
  200.13 + * General Public License Version 2 only ("GPL") or the Common
  200.14 + * Development and Distribution License("CDDL") (collectively, the
  200.15 + * "License"). You may not use this file except in compliance with the
  200.16 + * License. You can obtain a copy of the License at
  200.17 + * http://www.netbeans.org/cddl-gplv2.html
  200.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  200.19 + * specific language governing permissions and limitations under the
  200.20 + * License.  When distributing the software, include this License Header
  200.21 + * Notice in each file and include the License file at
  200.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  200.23 + * particular file as subject to the "Classpath" exception as provided
  200.24 + * by Oracle in the GPL Version 2 section of the License file that
  200.25 + * accompanied this code. If applicable, add the following below the
  200.26 + * License Header, with the fields enclosed by brackets [] replaced by
  200.27 + * your own identifying information:
  200.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  200.29 + *
  200.30 + * Contributor(s):
  200.31 + *
  200.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  200.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  200.34 + *
  200.35 + * If you wish your version of this file to be governed by only the CDDL
  200.36 + * or only the GPL Version 2, indicate your decision by adding
  200.37 + * "[Contributor] elects to include this software in this distribution
  200.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  200.39 + * single choice of license, a recipient has the option to distribute
  200.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  200.41 + * to extend the choice of license to its licensees as provided above.
  200.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  200.43 + * Version 2 license, then the option applies only if the new code is
  200.44 + * made subject to such option by the copyright holder.
  200.45 + */
  200.46 +package org.netbeans.html.kofx;
  200.47 +
  200.48 +import java.io.ByteArrayInputStream;
  200.49 +import java.io.ByteArrayOutputStream;
  200.50 +import java.io.IOException;
  200.51 +import java.io.InputStream;
  200.52 +import java.io.OutputStream;
  200.53 +import java.io.Reader;
  200.54 +import java.net.URI;
  200.55 +import java.net.URISyntaxException;
  200.56 +import java.util.ArrayList;
  200.57 +import java.util.List;
  200.58 +import java.util.logging.Level;
  200.59 +import java.util.logging.Logger;
  200.60 +import org.glassfish.grizzly.PortRange;
  200.61 +import org.glassfish.grizzly.http.server.HttpHandler;
  200.62 +import org.glassfish.grizzly.http.server.HttpServer;
  200.63 +import org.glassfish.grizzly.http.server.NetworkListener;
  200.64 +import org.glassfish.grizzly.http.server.Request;
  200.65 +import org.glassfish.grizzly.http.server.Response;
  200.66 +import org.glassfish.grizzly.http.server.ServerConfiguration;
  200.67 +import org.glassfish.grizzly.websockets.WebSocket;
  200.68 +import org.glassfish.grizzly.websockets.WebSocketAddOn;
  200.69 +import org.glassfish.grizzly.websockets.WebSocketApplication;
  200.70 +import org.glassfish.grizzly.websockets.WebSocketEngine;
  200.71 +
  200.72 +/**
  200.73 + *
  200.74 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  200.75 + */
  200.76 +final class DynamicHTTP extends HttpHandler {
  200.77 +    private static final Logger LOG = Logger.getLogger(DynamicHTTP.class.getName());
  200.78 +    private static int resourcesCount;
  200.79 +    private static List<Resource> resources;
  200.80 +    private static ServerConfiguration conf;
  200.81 +    private static HttpServer server;
  200.82 +    
  200.83 +    private DynamicHTTP() {
  200.84 +    }
  200.85 +    
  200.86 +    static URI initServer() throws Exception {
  200.87 +        server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
  200.88 +        final WebSocketAddOn addon = new WebSocketAddOn();
  200.89 +        for (NetworkListener listener : server.getListeners()) {
  200.90 +            listener.registerAddOn(addon);
  200.91 +        }        
  200.92 +        resources = new ArrayList<Resource>();
  200.93 +
  200.94 +        conf = server.getServerConfiguration();
  200.95 +        final DynamicHTTP dh = new DynamicHTTP();
  200.96 +
  200.97 +        conf.addHttpHandler(dh, "/");
  200.98 +        
  200.99 +        server.start();
 200.100 +
 200.101 +        return pageURL("http", server, "/test.html");
 200.102 +    }
 200.103 +    
 200.104 +    @Override
 200.105 +    public void service(Request request, Response response) throws Exception {
 200.106 +        if ("/test.html".equals(request.getRequestURI())) {
 200.107 +            response.setContentType("text/html");
 200.108 +            final InputStream is = DynamicHTTP.class.getResourceAsStream("test.html");
 200.109 +            copyStream(is, response.getOutputStream(), null);
 200.110 +            return;
 200.111 +        }
 200.112 +        if ("/dynamic".equals(request.getRequestURI())) {
 200.113 +            String mimeType = request.getParameter("mimeType");
 200.114 +            List<String> params = new ArrayList<String>();
 200.115 +            boolean webSocket = false;
 200.116 +            for (int i = 0;; i++) {
 200.117 +                String p = request.getParameter("param" + i);
 200.118 +                if (p == null) {
 200.119 +                    break;
 200.120 +                }
 200.121 +                if ("protocol:ws".equals(p)) {
 200.122 +                    webSocket = true;
 200.123 +                    continue;
 200.124 +                }
 200.125 +                params.add(p);
 200.126 +            }
 200.127 +            final String cnt = request.getParameter("content");
 200.128 +            String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
 200.129 +            ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
 200.130 +            URI url;
 200.131 +            final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
 200.132 +            if (webSocket) {
 200.133 +                url = registerWebSocket(res);
 200.134 +            } else {
 200.135 +                url = registerResource(res);
 200.136 +            }
 200.137 +            response.getWriter().write(url.toString());
 200.138 +            response.getWriter().write("\n");
 200.139 +            return;
 200.140 +        }
 200.141 +
 200.142 +        for (Resource r : resources) {
 200.143 +            if (r.httpPath.equals(request.getRequestURI())) {
 200.144 +                response.setContentType(r.httpType);
 200.145 +                r.httpContent.reset();
 200.146 +                String[] params = null;
 200.147 +                if (r.parameters.length != 0) {
 200.148 +                    params = new String[r.parameters.length];
 200.149 +                    for (int i = 0; i < r.parameters.length; i++) {
 200.150 +                        params[i] = request.getParameter(r.parameters[i]);
 200.151 +                        if (params[i] == null) {
 200.152 +                            if ("http.method".equals(r.parameters[i])) {
 200.153 +                                params[i] = request.getMethod().toString();
 200.154 +                            } else if ("http.requestBody".equals(r.parameters[i])) {
 200.155 +                                Reader rdr = request.getReader();
 200.156 +                                StringBuilder sb = new StringBuilder();
 200.157 +                                for (;;) {
 200.158 +                                    int ch = rdr.read();
 200.159 +                                    if (ch == -1) {
 200.160 +                                        break;
 200.161 +                                    }
 200.162 +                                    sb.append((char) ch);
 200.163 +                                }
 200.164 +                                params[i] = sb.toString();
 200.165 +                            }
 200.166 +                        }
 200.167 +                        if (params[i] == null) {
 200.168 +                            params[i] = "null";
 200.169 +                        }
 200.170 +                    }
 200.171 +                }
 200.172 +
 200.173 +                copyStream(r.httpContent, response.getOutputStream(), null, params);
 200.174 +            }
 200.175 +        }
 200.176 +    }
 200.177 +    
 200.178 +    private URI registerWebSocket(Resource r) {
 200.179 +        WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
 200.180 +        return pageURL("ws", server, r.httpPath);
 200.181 +    }
 200.182 +
 200.183 +    private URI registerResource(Resource r) {
 200.184 +        if (!resources.contains(r)) {
 200.185 +            resources.add(r);
 200.186 +            conf.addHttpHandler(this, r.httpPath);
 200.187 +        }
 200.188 +        return pageURL("http", server, r.httpPath);
 200.189 +    }
 200.190 +    
 200.191 +    private static URI pageURL(String proto, HttpServer server, final String page) {
 200.192 +        NetworkListener listener = server.getListeners().iterator().next();
 200.193 +        int port = listener.getPort();
 200.194 +        try {
 200.195 +            return new URI(proto + "://localhost:" + port + page);
 200.196 +        } catch (URISyntaxException ex) {
 200.197 +            throw new IllegalStateException(ex);
 200.198 +        }
 200.199 +    }
 200.200 +    
 200.201 +    static final class Resource {
 200.202 +
 200.203 +        final InputStream httpContent;
 200.204 +        final String httpType;
 200.205 +        final String httpPath;
 200.206 +        final String[] parameters;
 200.207 +
 200.208 +        Resource(InputStream httpContent, String httpType, String httpPath,
 200.209 +            String[] parameters) {
 200.210 +            httpContent.mark(Integer.MAX_VALUE);
 200.211 +            this.httpContent = httpContent;
 200.212 +            this.httpType = httpType;
 200.213 +            this.httpPath = httpPath;
 200.214 +            this.parameters = parameters;
 200.215 +        }
 200.216 +    }
 200.217 +
 200.218 +    static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
 200.219 +        for (;;) {
 200.220 +            int ch = is.read();
 200.221 +            if (ch == -1) {
 200.222 +                break;
 200.223 +            }
 200.224 +            if (ch == '$' && params.length > 0) {
 200.225 +                int cnt = is.read() - '0';
 200.226 +                if (baseURL != null && cnt == 'U' - '0') {
 200.227 +                    os.write(baseURL.getBytes("UTF-8"));
 200.228 +                } else {
 200.229 +                    if (cnt >= 0 && cnt < params.length) {
 200.230 +                        os.write(params[cnt].getBytes("UTF-8"));
 200.231 +                    } else {
 200.232 +                        os.write('$');
 200.233 +                        os.write(cnt + '0');
 200.234 +                    }
 200.235 +                }
 200.236 +            } else {
 200.237 +                os.write(ch);
 200.238 +            }
 200.239 +        }
 200.240 +    }
 200.241 +    
 200.242 +    private static class WS extends WebSocketApplication {
 200.243 +        private final Resource r;
 200.244 +
 200.245 +        private WS(Resource r) {
 200.246 +            this.r = r;
 200.247 +        }
 200.248 +
 200.249 +        @Override
 200.250 +        public void onMessage(WebSocket socket, String text) {
 200.251 +            try {
 200.252 +                r.httpContent.reset();
 200.253 +                ByteArrayOutputStream out = new ByteArrayOutputStream();
 200.254 +                copyStream(r.httpContent, out, null, text);
 200.255 +                String s = new String(out.toByteArray(), "UTF-8");
 200.256 +                socket.send(s);
 200.257 +            } catch (IOException ex) {
 200.258 +                LOG.log(Level.WARNING, "Error processing message " + text, ex);
 200.259 +            }
 200.260 +        }
 200.261 +    }
 200.262 +}
   201.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   201.2 +++ b/ko-fx/src/test/java/org/netbeans/html/kofx/KOFx.java	Tue Jan 07 08:21:57 2014 +0100
   201.3 @@ -0,0 +1,118 @@
   201.4 +/**
   201.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   201.6 + *
   201.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   201.8 + *
   201.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  201.10 + * Other names may be trademarks of their respective owners.
  201.11 + *
  201.12 + * The contents of this file are subject to the terms of either the GNU
  201.13 + * General Public License Version 2 only ("GPL") or the Common
  201.14 + * Development and Distribution License("CDDL") (collectively, the
  201.15 + * "License"). You may not use this file except in compliance with the
  201.16 + * License. You can obtain a copy of the License at
  201.17 + * http://www.netbeans.org/cddl-gplv2.html
  201.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  201.19 + * specific language governing permissions and limitations under the
  201.20 + * License.  When distributing the software, include this License Header
  201.21 + * Notice in each file and include the License file at
  201.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  201.23 + * particular file as subject to the "Classpath" exception as provided
  201.24 + * by Oracle in the GPL Version 2 section of the License file that
  201.25 + * accompanied this code. If applicable, add the following below the
  201.26 + * License Header, with the fields enclosed by brackets [] replaced by
  201.27 + * your own identifying information:
  201.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  201.29 + *
  201.30 + * Contributor(s):
  201.31 + *
  201.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  201.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  201.34 + *
  201.35 + * If you wish your version of this file to be governed by only the CDDL
  201.36 + * or only the GPL Version 2, indicate your decision by adding
  201.37 + * "[Contributor] elects to include this software in this distribution
  201.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  201.39 + * single choice of license, a recipient has the option to distribute
  201.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  201.41 + * to extend the choice of license to its licensees as provided above.
  201.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  201.43 + * Version 2 license, then the option applies only if the new code is
  201.44 + * made subject to such option by the copyright holder.
  201.45 + */
  201.46 +package org.netbeans.html.kofx;
  201.47 +
  201.48 +import java.io.Closeable;
  201.49 +import java.lang.reflect.InvocationTargetException;
  201.50 +import java.lang.reflect.Method;
  201.51 +import javafx.application.Platform;
  201.52 +import org.apidesign.html.boot.spi.Fn;
  201.53 +import org.testng.ITest;
  201.54 +import org.testng.annotations.Test;
  201.55 +
  201.56 +/**
  201.57 + *
  201.58 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  201.59 + */
  201.60 +public final class KOFx implements ITest, Runnable {
  201.61 +    private final Fn.Presenter p;
  201.62 +    private final Method m;
  201.63 +    private Object result;
  201.64 +    private Object inst;
  201.65 +    private int count;
  201.66 +
  201.67 +    KOFx(Fn.Presenter p, Method m) {
  201.68 +        this.p = p;
  201.69 +        this.m = m;
  201.70 +    }
  201.71 +
  201.72 +    @Override
  201.73 +    public String getTestName() {
  201.74 +        return m.getName();
  201.75 +    }
  201.76 +
  201.77 +    @Test
  201.78 +    public synchronized void executeTest() throws Exception {
  201.79 +        if (result == null) {
  201.80 +            Platform.runLater(this);
  201.81 +            wait();
  201.82 +        }
  201.83 +        if (result instanceof Exception) {
  201.84 +            throw (Exception)result;
  201.85 +        }
  201.86 +        if (result instanceof Error) {
  201.87 +            throw (Error)result;
  201.88 +        }
  201.89 +    }
  201.90 +
  201.91 +    @Override
  201.92 +    public synchronized void run() {
  201.93 +        boolean notify = true;
  201.94 +        try (Closeable a = Fn.activate(p)) {
  201.95 +            if (inst == null) {
  201.96 +                inst = m.getDeclaringClass().newInstance();
  201.97 +            }
  201.98 +            result = m.invoke(inst);
  201.99 +            if (result == null) {
 201.100 +                result = this;
 201.101 +            }
 201.102 +        } catch (InvocationTargetException ex) {
 201.103 +            Throwable r = ex.getTargetException();
 201.104 +            if (r instanceof InterruptedException) {
 201.105 +                if (count++ < 10000) {
 201.106 +                    notify = false;
 201.107 +                    Platform.runLater(this);
 201.108 +                    return;
 201.109 +                }
 201.110 +            }
 201.111 +            result = r;
 201.112 +        } catch (Exception ex) {
 201.113 +            result = ex;
 201.114 +        } finally {
 201.115 +            if (notify) {
 201.116 +                notifyAll();
 201.117 +            }
 201.118 +        }
 201.119 +    }
 201.120 +    
 201.121 +}
   202.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   202.2 +++ b/ko-fx/src/test/java/org/netbeans/html/kofx/KnockoutFXTest.java	Tue Jan 07 08:21:57 2014 +0100
   202.3 @@ -0,0 +1,229 @@
   202.4 +/**
   202.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   202.6 + *
   202.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   202.8 + *
   202.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  202.10 + * Other names may be trademarks of their respective owners.
  202.11 + *
  202.12 + * The contents of this file are subject to the terms of either the GNU
  202.13 + * General Public License Version 2 only ("GPL") or the Common
  202.14 + * Development and Distribution License("CDDL") (collectively, the
  202.15 + * "License"). You may not use this file except in compliance with the
  202.16 + * License. You can obtain a copy of the License at
  202.17 + * http://www.netbeans.org/cddl-gplv2.html
  202.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  202.19 + * specific language governing permissions and limitations under the
  202.20 + * License.  When distributing the software, include this License Header
  202.21 + * Notice in each file and include the License file at
  202.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  202.23 + * particular file as subject to the "Classpath" exception as provided
  202.24 + * by Oracle in the GPL Version 2 section of the License file that
  202.25 + * accompanied this code. If applicable, add the following below the
  202.26 + * License Header, with the fields enclosed by brackets [] replaced by
  202.27 + * your own identifying information:
  202.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  202.29 + *
  202.30 + * Contributor(s):
  202.31 + *
  202.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  202.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  202.34 + *
  202.35 + * If you wish your version of this file to be governed by only the CDDL
  202.36 + * or only the GPL Version 2, indicate your decision by adding
  202.37 + * "[Contributor] elects to include this software in this distribution
  202.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  202.39 + * single choice of license, a recipient has the option to distribute
  202.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  202.41 + * to extend the choice of license to its licensees as provided above.
  202.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  202.43 + * Version 2 license, then the option applies only if the new code is
  202.44 + * made subject to such option by the copyright holder.
  202.45 + */
  202.46 +package org.netbeans.html.kofx;
  202.47 +
  202.48 +import java.io.BufferedReader;
  202.49 +import java.io.IOException;
  202.50 +import java.io.InputStreamReader;
  202.51 +import java.lang.annotation.Annotation;
  202.52 +import java.lang.reflect.Method;
  202.53 +import java.net.URI;
  202.54 +import java.net.URISyntaxException;
  202.55 +import java.net.URL;
  202.56 +import java.net.URLConnection;
  202.57 +import java.util.ArrayList;
  202.58 +import java.util.List;
  202.59 +import java.util.Map;
  202.60 +import java.util.concurrent.Executors;
  202.61 +import net.java.html.BrwsrCtx;
  202.62 +import net.java.html.boot.BrowserBuilder;
  202.63 +import net.java.html.js.JavaScriptBody;
  202.64 +import org.netbeans.html.boot.impl.FnContext;
  202.65 +import org.apidesign.html.boot.spi.Fn;
  202.66 +import org.apidesign.html.context.spi.Contexts;
  202.67 +import org.apidesign.html.json.spi.Technology;
  202.68 +import org.apidesign.html.json.spi.Transfer;
  202.69 +import org.apidesign.html.json.spi.WSTransfer;
  202.70 +import org.apidesign.html.json.tck.KOTest;
  202.71 +import org.apidesign.html.json.tck.KnockoutTCK;
  202.72 +import org.json.JSONException;
  202.73 +import org.json.JSONObject;
  202.74 +import org.openide.util.lookup.ServiceProvider;
  202.75 +import org.testng.annotations.Factory;
  202.76 +import static org.testng.Assert.*;
  202.77 +
  202.78 +/**
  202.79 + *
  202.80 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  202.81 + */
  202.82 +@ServiceProvider(service = KnockoutTCK.class)
  202.83 +public final class KnockoutFXTest extends KnockoutTCK {
  202.84 +    private static Class<?> browserClass;
  202.85 +    private static Fn.Presenter browserContext;
  202.86 +    
  202.87 +    public KnockoutFXTest() {
  202.88 +    }
  202.89 +    
  202.90 +    @Factory public static Object[] compatibilityTests() throws Exception {
  202.91 +        Class[] arr = testClasses();
  202.92 +        for (int i = 0; i < arr.length; i++) {
  202.93 +            assertEquals(
  202.94 +                arr[i].getClassLoader(),
  202.95 +                KnockoutFXTest.class.getClassLoader(),
  202.96 +                "All classes loaded by the same classloader"
  202.97 +            );
  202.98 +        }
  202.99 +        
 202.100 +        URI uri = DynamicHTTP.initServer();
 202.101 +    
 202.102 +        final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(KnockoutFXTest.class).
 202.103 +            loadPage(uri.toString()).
 202.104 +            invoke("initialized");
 202.105 +        
 202.106 +        Executors.newSingleThreadExecutor().submit(new Runnable() {
 202.107 +            @Override
 202.108 +            public void run() {
 202.109 +                bb.showAndWait();
 202.110 +            }
 202.111 +        });
 202.112 +        
 202.113 +        ClassLoader l = getClassLoader();
 202.114 +        List<Object> res = new ArrayList<Object>();
 202.115 +        for (int i = 0; i < arr.length; i++) {
 202.116 +            Class<?> c = Class.forName(arr[i].getName(), true, l);
 202.117 +            seekKOTests(c, res);
 202.118 +        }
 202.119 +        Class<?> c = Class.forName(LessCallbacksCheck.class.getName(), true, l);
 202.120 +        seekKOTests(c, res);
 202.121 +        return res.toArray();
 202.122 +    }
 202.123 +
 202.124 +    private static void seekKOTests(Class<?> c, List<Object> res) throws SecurityException, ClassNotFoundException {
 202.125 +        Class<? extends Annotation> koTest =
 202.126 +            c.getClassLoader().loadClass(KOTest.class.getName()).
 202.127 +            asSubclass(Annotation.class);
 202.128 +        for (Method m : c.getMethods()) {
 202.129 +            if (m.getAnnotation(koTest) != null) {
 202.130 +                res.add(new KOFx(browserContext, m));
 202.131 +            }
 202.132 +        }
 202.133 +    }
 202.134 +
 202.135 +    static synchronized ClassLoader getClassLoader() throws InterruptedException {
 202.136 +        while (browserClass == null) {
 202.137 +            KnockoutFXTest.class.wait();
 202.138 +        }
 202.139 +        return browserClass.getClassLoader();
 202.140 +    }
 202.141 +    
 202.142 +    public static synchronized void initialized(Class<?> browserCls) throws Exception {
 202.143 +        browserClass = browserCls;
 202.144 +        browserContext = Fn.activePresenter();
 202.145 +        KnockoutFXTest.class.notifyAll();
 202.146 +    }
 202.147 +    
 202.148 +    public static void initialized() throws Exception {
 202.149 +        Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(KnockoutFXTest.class.getName());
 202.150 +        Method m = classpathClass.getMethod("initialized", Class.class);
 202.151 +        m.invoke(null, KnockoutFXTest.class);
 202.152 +        browserContext = Fn.activePresenter();
 202.153 +    }
 202.154 +    
 202.155 +    @Override
 202.156 +    public BrwsrCtx createContext() {
 202.157 +        FXContext fx = new FXContext(browserContext);
 202.158 +        Contexts.Builder cb = Contexts.newBuilder().
 202.159 +            register(Technology.class, fx, 10).
 202.160 +            register(Transfer.class, fx, 10);
 202.161 +        if (fx.areWebSocketsSupported()) {
 202.162 +            cb.register(WSTransfer.class, fx, 10);
 202.163 +        }
 202.164 +        return cb.build();
 202.165 +    }
 202.166 +
 202.167 +    @Override
 202.168 +    public Object createJSON(Map<String, Object> values) {
 202.169 +        JSONObject json = new JSONObject();
 202.170 +        for (Map.Entry<String, Object> entry : values.entrySet()) {
 202.171 +            try {
 202.172 +                json.put(entry.getKey(), entry.getValue());
 202.173 +            } catch (JSONException ex) {
 202.174 +                throw new IllegalStateException(ex);
 202.175 +            }
 202.176 +        }
 202.177 +        return json;
 202.178 +    }
 202.179 +
 202.180 +    @Override
 202.181 +    @JavaScriptBody(args = { "s", "args" }, body = ""
 202.182 +        + "var f = new Function(s); "
 202.183 +        + "return f.apply(null, args);"
 202.184 +    )
 202.185 +    public native Object executeScript(String script, Object[] arguments);
 202.186 +
 202.187 +    @JavaScriptBody(args = {  }, body = 
 202.188 +          "var h;"
 202.189 +        + "if (!!window && !!window.location && !!window.location.href)\n"
 202.190 +        + "  h = window.location.href;\n"
 202.191 +        + "else "
 202.192 +        + "  h = null;"
 202.193 +        + "return h;\n"
 202.194 +    )
 202.195 +    private static native String findBaseURL();
 202.196 +    
 202.197 +    @Override
 202.198 +    public URI prepareURL(String content, String mimeType, String[] parameters) {
 202.199 +        try {
 202.200 +            final URL baseURL = new URL(findBaseURL());
 202.201 +            StringBuilder sb = new StringBuilder();
 202.202 +            sb.append("/dynamic?mimeType=").append(mimeType);
 202.203 +            for (int i = 0; i < parameters.length; i++) {
 202.204 +                sb.append("&param" + i).append("=").append(parameters[i]);
 202.205 +            }
 202.206 +            String mangle = content.replace("\n", "%0a")
 202.207 +                .replace("\"", "\\\"").replace(" ", "%20");
 202.208 +            sb.append("&content=").append(mangle);
 202.209 +
 202.210 +            URL query = new URL(baseURL, sb.toString());
 202.211 +            URLConnection c = query.openConnection();
 202.212 +            BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
 202.213 +            URI connectTo = new URI(br.readLine());
 202.214 +            return connectTo;
 202.215 +        } catch (IOException ex) {
 202.216 +            throw new IllegalStateException(ex);
 202.217 +        } catch (URISyntaxException ex) {
 202.218 +            throw new IllegalStateException(ex);
 202.219 +        }
 202.220 +    }
 202.221 +
 202.222 +    @Override
 202.223 +    public boolean canFailWebSocketTest() {
 202.224 +        try {
 202.225 +            Class.forName("java.util.function.Function");
 202.226 +            return false;
 202.227 +        } catch (ClassNotFoundException ex) {
 202.228 +            // running on JDK7, FX WebView WebSocket impl does not work
 202.229 +            return true;
 202.230 +        }
 202.231 +    }
 202.232 +}
   203.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   203.2 +++ b/ko-fx/src/test/java/org/netbeans/html/kofx/LessCallbacksCheck.java	Tue Jan 07 08:21:57 2014 +0100
   203.3 @@ -0,0 +1,82 @@
   203.4 +/**
   203.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   203.6 + *
   203.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   203.8 + *
   203.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  203.10 + * Other names may be trademarks of their respective owners.
  203.11 + *
  203.12 + * The contents of this file are subject to the terms of either the GNU
  203.13 + * General Public License Version 2 only ("GPL") or the Common
  203.14 + * Development and Distribution License("CDDL") (collectively, the
  203.15 + * "License"). You may not use this file except in compliance with the
  203.16 + * License. You can obtain a copy of the License at
  203.17 + * http://www.netbeans.org/cddl-gplv2.html
  203.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  203.19 + * specific language governing permissions and limitations under the
  203.20 + * License.  When distributing the software, include this License Header
  203.21 + * Notice in each file and include the License file at
  203.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  203.23 + * particular file as subject to the "Classpath" exception as provided
  203.24 + * by Oracle in the GPL Version 2 section of the License file that
  203.25 + * accompanied this code. If applicable, add the following below the
  203.26 + * License Header, with the fields enclosed by brackets [] replaced by
  203.27 + * your own identifying information:
  203.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  203.29 + *
  203.30 + * Contributor(s):
  203.31 + *
  203.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  203.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  203.34 + *
  203.35 + * If you wish your version of this file to be governed by only the CDDL
  203.36 + * or only the GPL Version 2, indicate your decision by adding
  203.37 + * "[Contributor] elects to include this software in this distribution
  203.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  203.39 + * single choice of license, a recipient has the option to distribute
  203.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  203.41 + * to extend the choice of license to its licensees as provided above.
  203.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  203.43 + * Version 2 license, then the option applies only if the new code is
  203.44 + * made subject to such option by the copyright holder.
  203.45 + */
  203.46 +package org.netbeans.html.kofx;
  203.47 +
  203.48 +import java.io.PrintWriter;
  203.49 +import java.io.StringWriter;
  203.50 +import net.java.html.json.ComputedProperty;
  203.51 +import net.java.html.json.Model;
  203.52 +import net.java.html.json.Property;
  203.53 +import org.apidesign.html.json.tck.KOTest;
  203.54 +
  203.55 +/**
  203.56 + *
  203.57 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  203.58 + */
  203.59 +@Model(className = "LessCalls", properties = {
  203.60 +    @Property(name = "value", type = int.class)
  203.61 +})
  203.62 +public class LessCallbacksCheck {
  203.63 +    private static StringWriter sw;
  203.64 +    
  203.65 +    @ComputedProperty static int plusOne(int value) {
  203.66 +        if (sw == null) {
  203.67 +            sw = new StringWriter();
  203.68 +        }
  203.69 +        new Exception("Who calls me?").printStackTrace(
  203.70 +            new PrintWriter(sw)
  203.71 +        );
  203.72 +        return value + 1;
  203.73 +    }
  203.74 +    
  203.75 +    @KOTest public void dontCallForInitialValueBackToJavaVM() {
  203.76 +        LessCalls m = new LessCalls(10).applyBindings();
  203.77 +        assert m.getPlusOne() == 11 : "Expecting 11: " + m.getPlusOne();
  203.78 +        
  203.79 +        assert sw != null : "StringWriter should be initialized: " + sw;
  203.80 +        
  203.81 +        if (sw.toString().contains("$JsCallbacks$")) {
  203.82 +            assert false : "Don't call for initial value via JsCallbacks:\n" + sw;
  203.83 +        }
  203.84 +    }
  203.85 +}
   204.1 --- a/ko-fx/src/test/resources/org/apidesign/html/kofx/test.html	Thu Dec 19 17:11:01 2013 +0100
   204.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   204.3 @@ -1,34 +0,0 @@
   204.4 -<!--
   204.5 -
   204.6 -    HTML via Java(tm) Language Bindings
   204.7 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   204.8 -
   204.9 -    This program is free software: you can redistribute it and/or modify
  204.10 -    it under the terms of the GNU General Public License as published by
  204.11 -    the Free Software Foundation, version 2 of the License.
  204.12 -
  204.13 -    This program is distributed in the hope that it will be useful,
  204.14 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
  204.15 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  204.16 -    GNU General Public License for more details. apidesign.org
  204.17 -    designates this particular file as subject to the
  204.18 -    "Classpath" exception as provided by apidesign.org
  204.19 -    in the License file that accompanied this code.
  204.20 -
  204.21 -    You should have received a copy of the GNU General Public License
  204.22 -    along with this program. Look for COPYING file in the top folder.
  204.23 -    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  204.24 -
  204.25 --->
  204.26 -<!DOCTYPE html>
  204.27 -<html>
  204.28 -    <head>
  204.29 -        <title>Knockout.fx Execution Harness</title>
  204.30 -        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  204.31 -        <meta name="viewport" content="width=device-width">
  204.32 -    </head>
  204.33 -    <body>
  204.34 -        <h1>Knockout.fx Execution Harness</h1>
  204.35 -    </body>
  204.36 -    <script></script>
  204.37 -</html>
   205.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   205.2 +++ b/ko-fx/src/test/resources/org/netbeans/html/kofx/test.html	Tue Jan 07 08:21:57 2014 +0100
   205.3 @@ -0,0 +1,56 @@
   205.4 +<!--
   205.5 +
   205.6 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   205.7 +
   205.8 +    Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   205.9 +
  205.10 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  205.11 +    Other names may be trademarks of their respective owners.
  205.12 +
  205.13 +    The contents of this file are subject to the terms of either the GNU
  205.14 +    General Public License Version 2 only ("GPL") or the Common
  205.15 +    Development and Distribution License("CDDL") (collectively, the
  205.16 +    "License"). You may not use this file except in compliance with the
  205.17 +    License. You can obtain a copy of the License at
  205.18 +    http://www.netbeans.org/cddl-gplv2.html
  205.19 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  205.20 +    specific language governing permissions and limitations under the
  205.21 +    License.  When distributing the software, include this License Header
  205.22 +    Notice in each file and include the License file at
  205.23 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  205.24 +    particular file as subject to the "Classpath" exception as provided
  205.25 +    by Oracle in the GPL Version 2 section of the License file that
  205.26 +    accompanied this code. If applicable, add the following below the
  205.27 +    License Header, with the fields enclosed by brackets [] replaced by
  205.28 +    your own identifying information:
  205.29 +    "Portions Copyrighted [year] [name of copyright owner]"
  205.30 +
  205.31 +    Contributor(s):
  205.32 +
  205.33 +    The Original Software is NetBeans. The Initial Developer of the Original
  205.34 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  205.35 +
  205.36 +    If you wish your version of this file to be governed by only the CDDL
  205.37 +    or only the GPL Version 2, indicate your decision by adding
  205.38 +    "[Contributor] elects to include this software in this distribution
  205.39 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
  205.40 +    single choice of license, a recipient has the option to distribute
  205.41 +    your version of this file under either the CDDL, the GPL Version 2 or
  205.42 +    to extend the choice of license to its licensees as provided above.
  205.43 +    However, if you add GPL Version 2 code and therefore, elected the GPL
  205.44 +    Version 2 license, then the option applies only if the new code is
  205.45 +    made subject to such option by the copyright holder.
  205.46 +
  205.47 +-->
  205.48 +<!DOCTYPE html>
  205.49 +<html>
  205.50 +    <head>
  205.51 +        <title>Knockout.fx Execution Harness</title>
  205.52 +        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  205.53 +        <meta name="viewport" content="width=device-width">
  205.54 +    </head>
  205.55 +    <body>
  205.56 +        <h1>Knockout.fx Execution Harness</h1>
  205.57 +    </body>
  205.58 +    <script></script>
  205.59 +</html>
   206.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   206.2 +++ b/ko-osgi-test/pom.xml	Tue Jan 07 08:21:57 2014 +0100
   206.3 @@ -0,0 +1,136 @@
   206.4 +<?xml version="1.0" encoding="UTF-8"?>
   206.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">
   206.6 +    <modelVersion>4.0.0</modelVersion>
   206.7 +    <parent>
   206.8 +        <groupId>org.netbeans.html</groupId>
   206.9 +        <artifactId>pom</artifactId>
  206.10 +        <version>0.7-SNAPSHOT</version>
  206.11 +    </parent>
  206.12 +    <name>KO Tests in an OSGi Container</name>
  206.13 +    <artifactId>ko-osgi-test</artifactId>
  206.14 +    <packaging>bundle</packaging>
  206.15 +    <description>Runs the TCK for Knockout in an OSGi Container</description>
  206.16 +    <properties>
  206.17 +        <netbeans.compile.on.save>none</netbeans.compile.on.save>
  206.18 +    </properties>
  206.19 +    <build>
  206.20 +        <plugins>
  206.21 +            <plugin>
  206.22 +                <groupId>org.apache.felix</groupId>
  206.23 +                <artifactId>maven-bundle-plugin</artifactId>
  206.24 +            </plugin>
  206.25 +            <plugin>
  206.26 +                <groupId>org.apache.maven.plugins</groupId>
  206.27 +                <artifactId>maven-compiler-plugin</artifactId>
  206.28 +                <version>2.3.2</version>
  206.29 +                <configuration>
  206.30 +                    <source>1.7</source>
  206.31 +                    <target>1.7</target>
  206.32 +                </configuration>
  206.33 +            </plugin>
  206.34 +            <plugin>
  206.35 +                <artifactId>maven-failsafe-plugin</artifactId>
  206.36 +                <version>2.16</version>
  206.37 +                <configuration>
  206.38 +                    <additionalClasspathElements>
  206.39 +                        <additionalClasspathElement>${project.build.directory}/${project.build.finalName}.jar</additionalClasspathElement>
  206.40 +                    </additionalClasspathElements>
  206.41 +                </configuration>
  206.42 +                <executions>
  206.43 +                    <execution>
  206.44 +                        <goals>
  206.45 +                            <goal>integration-test</goal>
  206.46 +                            <goal>verify</goal>
  206.47 +                        </goals>
  206.48 +                    </execution>
  206.49 +                </executions>
  206.50 +            </plugin>
  206.51 +        </plugins>
  206.52 +    </build>
  206.53 +    <dependencies>
  206.54 +        <dependency>
  206.55 +            <groupId>com.oracle</groupId>
  206.56 +            <artifactId>javafx</artifactId>
  206.57 +            <version>2.2</version>
  206.58 +            <scope>system</scope>
  206.59 +            <systemPath>${jfxrt.jar}</systemPath>
  206.60 +        </dependency>
  206.61 +        <dependency>
  206.62 +            <groupId>de.twentyeleven.skysail</groupId>
  206.63 +            <artifactId>org.json-osgi</artifactId>
  206.64 +        </dependency>
  206.65 +        <dependency>
  206.66 +            <groupId>org.netbeans.html</groupId>
  206.67 +            <artifactId>net.java.html.json</artifactId>
  206.68 +            <version>${project.version}</version>
  206.69 +        </dependency>
  206.70 +        <dependency>
  206.71 +            <groupId>org.testng</groupId>
  206.72 +            <artifactId>testng</artifactId>
  206.73 +            <scope>test</scope>
  206.74 +        </dependency>
  206.75 +        <dependency>
  206.76 +            <groupId>${project.groupId}</groupId>
  206.77 +            <artifactId>net.java.html.json.tck</artifactId>
  206.78 +            <version>${project.version}</version>
  206.79 +        </dependency>
  206.80 +        <dependency>
  206.81 +            <groupId>org.netbeans.api</groupId>
  206.82 +            <artifactId>org-openide-util-lookup</artifactId>
  206.83 +            <scope>provided</scope>
  206.84 +        </dependency>
  206.85 +        <dependency>
  206.86 +            <groupId>org.netbeans.html</groupId>
  206.87 +            <artifactId>net.java.html.boot</artifactId>
  206.88 +            <version>${project.version}</version>
  206.89 +            <type>jar</type>
  206.90 +        </dependency>
  206.91 +        <dependency>
  206.92 +            <groupId>${project.groupId}</groupId>
  206.93 +            <artifactId>ko-fx</artifactId>
  206.94 +            <version>${project.version}</version>
  206.95 +        </dependency>
  206.96 +        <dependency>
  206.97 +            <groupId>${project.groupId}</groupId>
  206.98 +            <artifactId>net.java.html.boot.fx</artifactId>
  206.99 +            <version>${project.version}</version>
 206.100 +            <scope>test</scope>
 206.101 +        </dependency>
 206.102 +        <dependency>
 206.103 +            <groupId>org.glassfish.grizzly</groupId>
 206.104 +            <artifactId>grizzly-http-server</artifactId>
 206.105 +            <version>2.3.3</version>
 206.106 +            <scope>test</scope>
 206.107 +        </dependency>
 206.108 +        <dependency>
 206.109 +            <groupId>org.glassfish.grizzly</groupId>
 206.110 +            <artifactId>grizzly-websockets-server</artifactId>
 206.111 +            <version>2.3.3</version>
 206.112 +            <scope>test</scope>
 206.113 +            <type>jar</type>
 206.114 +        </dependency>
 206.115 +        <dependency>
 206.116 +            <groupId>org.glassfish.grizzly</groupId>
 206.117 +            <artifactId>grizzly-http-servlet</artifactId>
 206.118 +            <version>2.3.3</version>
 206.119 +            <scope>test</scope>
 206.120 +        </dependency>    
 206.121 +        <dependency>
 206.122 +            <groupId>javax.servlet</groupId>
 206.123 +            <artifactId>javax.servlet-api</artifactId>
 206.124 +            <scope>test</scope>
 206.125 +            <version>3.1.0</version>
 206.126 +        </dependency>
 206.127 +        <dependency>
 206.128 +            <groupId>org.eclipse</groupId>
 206.129 +            <artifactId>org.eclipse.osgi</artifactId>
 206.130 +            <version>3.8.0.v20120529-1548</version>
 206.131 +        </dependency>
 206.132 +        <dependency>
 206.133 +            <groupId>${project.groupId}</groupId>
 206.134 +            <artifactId>equinox-agentclass-hook</artifactId>
 206.135 +            <version>${project.version}</version>
 206.136 +            <scope>test</scope>
 206.137 +        </dependency>
 206.138 +    </dependencies>
 206.139 +</project>
 206.140 \ No newline at end of file
   207.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   207.2 +++ b/ko-osgi-test/src/main/java/org/netbeans/html/ko/osgi/test/KnockoutEquinoxTCKImpl.java	Tue Jan 07 08:21:57 2014 +0100
   207.3 @@ -0,0 +1,219 @@
   207.4 +/**
   207.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   207.6 + *
   207.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   207.8 + *
   207.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  207.10 + * Other names may be trademarks of their respective owners.
  207.11 + *
  207.12 + * The contents of this file are subject to the terms of either the GNU
  207.13 + * General Public License Version 2 only ("GPL") or the Common
  207.14 + * Development and Distribution License("CDDL") (collectively, the
  207.15 + * "License"). You may not use this file except in compliance with the
  207.16 + * License. You can obtain a copy of the License at
  207.17 + * http://www.netbeans.org/cddl-gplv2.html
  207.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  207.19 + * specific language governing permissions and limitations under the
  207.20 + * License.  When distributing the software, include this License Header
  207.21 + * Notice in each file and include the License file at
  207.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  207.23 + * particular file as subject to the "Classpath" exception as provided
  207.24 + * by Oracle in the GPL Version 2 section of the License file that
  207.25 + * accompanied this code. If applicable, add the following below the
  207.26 + * License Header, with the fields enclosed by brackets [] replaced by
  207.27 + * your own identifying information:
  207.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  207.29 + *
  207.30 + * Contributor(s):
  207.31 + *
  207.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  207.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  207.34 + *
  207.35 + * If you wish your version of this file to be governed by only the CDDL
  207.36 + * or only the GPL Version 2, indicate your decision by adding
  207.37 + * "[Contributor] elects to include this software in this distribution
  207.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  207.39 + * single choice of license, a recipient has the option to distribute
  207.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  207.41 + * to extend the choice of license to its licensees as provided above.
  207.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  207.43 + * Version 2 license, then the option applies only if the new code is
  207.44 + * made subject to such option by the copyright holder.
  207.45 + */
  207.46 +package org.netbeans.html.ko.osgi.test;
  207.47 +
  207.48 +import java.io.BufferedReader;
  207.49 +import java.io.IOException;
  207.50 +import java.io.InputStreamReader;
  207.51 +import java.lang.reflect.Method;
  207.52 +import java.net.URI;
  207.53 +import java.net.URISyntaxException;
  207.54 +import java.net.URL;
  207.55 +import java.net.URLConnection;
  207.56 +import java.util.Map;
  207.57 +import java.util.concurrent.Callable;
  207.58 +import java.util.concurrent.Executors;
  207.59 +import net.java.html.BrwsrCtx;
  207.60 +import net.java.html.boot.BrowserBuilder;
  207.61 +import net.java.html.js.JavaScriptBody;
  207.62 +import org.apidesign.html.boot.spi.Fn;
  207.63 +import org.apidesign.html.context.spi.Contexts;
  207.64 +import org.apidesign.html.json.spi.Technology;
  207.65 +import org.apidesign.html.json.spi.Transfer;
  207.66 +import org.apidesign.html.json.tck.KnockoutTCK;
  207.67 +import org.json.JSONException;
  207.68 +import org.json.JSONObject;
  207.69 +import org.openide.util.lookup.ServiceProvider;
  207.70 +import org.osgi.framework.Bundle;
  207.71 +import org.osgi.framework.BundleContext;
  207.72 +import org.osgi.framework.FrameworkUtil;
  207.73 +
  207.74 +/**
  207.75 + *
  207.76 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  207.77 + */
  207.78 +@ServiceProvider(service = KnockoutTCK.class)
  207.79 +public class KnockoutEquinoxTCKImpl extends KnockoutTCK implements Callable<Class[]> {
  207.80 +    
  207.81 +    private static Fn.Presenter browserContext;
  207.82 +
  207.83 +    public static Class loadOSGiClass(String name, BundleContext ctx) throws Exception {
  207.84 +        for (Bundle b : ctx.getBundles()) {
  207.85 +            try {
  207.86 +                Class<?> osgiClass = b.loadClass(name);
  207.87 +                if (osgiClass != null && osgiClass.getClassLoader() != ClassLoader.getSystemClassLoader()) {
  207.88 +                    return osgiClass;
  207.89 +                }
  207.90 +            } catch (ClassNotFoundException cnfe) {
  207.91 +                // go on
  207.92 +            }
  207.93 +        }
  207.94 +        throw new IllegalStateException("Cannot load " + name + " from the OSGi container!");
  207.95 +    }
  207.96 +
  207.97 +    @Override
  207.98 +    public Class[] call() throws Exception {
  207.99 +        return testClasses();
 207.100 +    }
 207.101 +    
 207.102 +    public static void start(URI server) throws Exception {
 207.103 +        final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(KnockoutEquinoxTCKImpl.class).
 207.104 +            loadPage(server.toString()).
 207.105 +            invoke("initialized");
 207.106 +
 207.107 +        Executors.newSingleThreadExecutor().submit(new Runnable() {
 207.108 +            @Override
 207.109 +            public void run() {
 207.110 +                try {
 207.111 +                    final ClassLoader osgiClassLoader = BrowserBuilder.class.getClassLoader();
 207.112 +                    Thread.currentThread().setContextClassLoader(osgiClassLoader);
 207.113 +                    bb.showAndWait();
 207.114 +                } catch (Throwable t) {
 207.115 +                    t.printStackTrace();
 207.116 +                }
 207.117 +            }
 207.118 +        });
 207.119 +    }
 207.120 +
 207.121 +    public static void initialized() throws Exception {
 207.122 +        Bundle bundle = FrameworkUtil.getBundle(KnockoutEquinoxTCKImpl.class);
 207.123 +        if (bundle == null) {
 207.124 +            throw new IllegalStateException(
 207.125 +                "Should be loaded from a bundle. But was: " + KnockoutEquinoxTCKImpl.class.getClassLoader()
 207.126 +            );
 207.127 +        }
 207.128 +        Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(
 207.129 +            "org.netbeans.html.ko.osgi.test.KnockoutEquinoxIT"
 207.130 +        );
 207.131 +        Method m = classpathClass.getMethod("initialized", Class.class, Object.class);
 207.132 +        browserContext = Fn.activePresenter();
 207.133 +        m.invoke(null, KnockoutEquinoxTCKImpl.class, browserContext);
 207.134 +    }
 207.135 +    
 207.136 +    @Override
 207.137 +    public BrwsrCtx createContext() {
 207.138 +        try {
 207.139 +            Class<?> fxCls = loadOSGiClass(
 207.140 +                "org.netbeans.html.kofx.FXContext",
 207.141 +                FrameworkUtil.getBundle(KnockoutEquinoxTCKImpl.class).getBundleContext()
 207.142 +            );
 207.143 +            Object fx = fxCls.getConstructor(Fn.Presenter.class).newInstance(browserContext);
 207.144 +            Contexts.Builder cb = Contexts.newBuilder().
 207.145 +                register(Technology.class, (Technology)fx, 10).
 207.146 +                register(Transfer.class, (Transfer)fx, 10);
 207.147 +//        if (fx.areWebSocketsSupported()) {
 207.148 +//            cb.register(WSTransfer.class, fx, 10);
 207.149 +//        }
 207.150 +            return cb.build();
 207.151 +        } catch (Exception ex) {
 207.152 +            throw new IllegalStateException(ex);
 207.153 +        }
 207.154 +    }
 207.155 +
 207.156 +    @Override
 207.157 +    public Object createJSON(Map<String, Object> values) {
 207.158 +        JSONObject json = new JSONObject();
 207.159 +        for (Map.Entry<String, Object> entry : values.entrySet()) {
 207.160 +            try {
 207.161 +                json.put(entry.getKey(), entry.getValue());
 207.162 +            } catch (JSONException ex) {
 207.163 +                throw new IllegalStateException(ex);
 207.164 +            }
 207.165 +        }
 207.166 +        return json;
 207.167 +    }
 207.168 +
 207.169 +    @Override
 207.170 +    @JavaScriptBody(args = { "s", "args" }, body = ""
 207.171 +        + "var f = new Function(s); "
 207.172 +        + "return f.apply(null, args);"
 207.173 +    )
 207.174 +    public native Object executeScript(String script, Object[] arguments);
 207.175 +
 207.176 +    @JavaScriptBody(args = {  }, body = 
 207.177 +          "var h;"
 207.178 +        + "if (!!window && !!window.location && !!window.location.href)\n"
 207.179 +        + "  h = window.location.href;\n"
 207.180 +        + "else "
 207.181 +        + "  h = null;"
 207.182 +        + "return h;\n"
 207.183 +    )
 207.184 +    private static native String findBaseURL();
 207.185 +    
 207.186 +    @Override
 207.187 +    public URI prepareURL(String content, String mimeType, String[] parameters) {
 207.188 +        try {
 207.189 +            final URL baseURL = new URL(findBaseURL());
 207.190 +            StringBuilder sb = new StringBuilder();
 207.191 +            sb.append("/dynamic?mimeType=").append(mimeType);
 207.192 +            for (int i = 0; i < parameters.length; i++) {
 207.193 +                sb.append("&param" + i).append("=").append(parameters[i]);
 207.194 +            }
 207.195 +            String mangle = content.replace("\n", "%0a")
 207.196 +                .replace("\"", "\\\"").replace(" ", "%20");
 207.197 +            sb.append("&content=").append(mangle);
 207.198 +
 207.199 +            URL query = new URL(baseURL, sb.toString());
 207.200 +            URLConnection c = query.openConnection();
 207.201 +            BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
 207.202 +            URI connectTo = new URI(br.readLine());
 207.203 +            return connectTo;
 207.204 +        } catch (IOException ex) {
 207.205 +            throw new IllegalStateException(ex);
 207.206 +        } catch (URISyntaxException ex) {
 207.207 +            throw new IllegalStateException(ex);
 207.208 +        }
 207.209 +    }
 207.210 +
 207.211 +    @Override
 207.212 +    public boolean canFailWebSocketTest() {
 207.213 +        try {
 207.214 +            Class.forName("java.util.function.Function");
 207.215 +            return false;
 207.216 +        } catch (ClassNotFoundException ex) {
 207.217 +            // running on JDK7, FX WebView WebSocket impl does not work
 207.218 +            return true;
 207.219 +        }
 207.220 +    }
 207.221 +
 207.222 +}
   208.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   208.2 +++ b/ko-osgi-test/src/test/java/org/netbeans/html/ko/osgi/test/DynamicHTTP.java	Tue Jan 07 08:21:57 2014 +0100
   208.3 @@ -0,0 +1,259 @@
   208.4 +/**
   208.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   208.6 + *
   208.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   208.8 + *
   208.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  208.10 + * Other names may be trademarks of their respective owners.
  208.11 + *
  208.12 + * The contents of this file are subject to the terms of either the GNU
  208.13 + * General Public License Version 2 only ("GPL") or the Common
  208.14 + * Development and Distribution License("CDDL") (collectively, the
  208.15 + * "License"). You may not use this file except in compliance with the
  208.16 + * License. You can obtain a copy of the License at
  208.17 + * http://www.netbeans.org/cddl-gplv2.html
  208.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  208.19 + * specific language governing permissions and limitations under the
  208.20 + * License.  When distributing the software, include this License Header
  208.21 + * Notice in each file and include the License file at
  208.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  208.23 + * particular file as subject to the "Classpath" exception as provided
  208.24 + * by Oracle in the GPL Version 2 section of the License file that
  208.25 + * accompanied this code. If applicable, add the following below the
  208.26 + * License Header, with the fields enclosed by brackets [] replaced by
  208.27 + * your own identifying information:
  208.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  208.29 + *
  208.30 + * Contributor(s):
  208.31 + *
  208.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  208.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  208.34 + *
  208.35 + * If you wish your version of this file to be governed by only the CDDL
  208.36 + * or only the GPL Version 2, indicate your decision by adding
  208.37 + * "[Contributor] elects to include this software in this distribution
  208.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  208.39 + * single choice of license, a recipient has the option to distribute
  208.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  208.41 + * to extend the choice of license to its licensees as provided above.
  208.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  208.43 + * Version 2 license, then the option applies only if the new code is
  208.44 + * made subject to such option by the copyright holder.
  208.45 + */
  208.46 +package org.netbeans.html.ko.osgi.test;
  208.47 +
  208.48 +import java.io.ByteArrayInputStream;
  208.49 +import java.io.ByteArrayOutputStream;
  208.50 +import java.io.IOException;
  208.51 +import java.io.InputStream;
  208.52 +import java.io.OutputStream;
  208.53 +import java.io.Reader;
  208.54 +import java.net.URI;
  208.55 +import java.net.URISyntaxException;
  208.56 +import java.util.ArrayList;
  208.57 +import java.util.List;
  208.58 +import java.util.logging.Level;
  208.59 +import java.util.logging.Logger;
  208.60 +import org.glassfish.grizzly.PortRange;
  208.61 +import org.glassfish.grizzly.http.server.HttpHandler;
  208.62 +import org.glassfish.grizzly.http.server.HttpServer;
  208.63 +import org.glassfish.grizzly.http.server.NetworkListener;
  208.64 +import org.glassfish.grizzly.http.server.Request;
  208.65 +import org.glassfish.grizzly.http.server.Response;
  208.66 +import org.glassfish.grizzly.http.server.ServerConfiguration;
  208.67 +import org.glassfish.grizzly.websockets.WebSocket;
  208.68 +import org.glassfish.grizzly.websockets.WebSocketAddOn;
  208.69 +import org.glassfish.grizzly.websockets.WebSocketApplication;
  208.70 +import org.glassfish.grizzly.websockets.WebSocketEngine;
  208.71 +
  208.72 +/**
  208.73 + *
  208.74 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  208.75 + */
  208.76 +final class DynamicHTTP extends HttpHandler {
  208.77 +    private static final Logger LOG = Logger.getLogger(DynamicHTTP.class.getName());
  208.78 +    private static int resourcesCount;
  208.79 +    private static List<Resource> resources;
  208.80 +    private static ServerConfiguration conf;
  208.81 +    private static HttpServer server;
  208.82 +    
  208.83 +    private DynamicHTTP() {
  208.84 +    }
  208.85 +    
  208.86 +    static URI initServer() throws Exception {
  208.87 +        server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
  208.88 +        final WebSocketAddOn addon = new WebSocketAddOn();
  208.89 +        for (NetworkListener listener : server.getListeners()) {
  208.90 +            listener.registerAddOn(addon);
  208.91 +        }        
  208.92 +        resources = new ArrayList<Resource>();
  208.93 +
  208.94 +        conf = server.getServerConfiguration();
  208.95 +        final DynamicHTTP dh = new DynamicHTTP();
  208.96 +
  208.97 +        conf.addHttpHandler(dh, "/");
  208.98 +        
  208.99 +        server.start();
 208.100 +
 208.101 +        return pageURL("http", server, "/test.html");
 208.102 +    }
 208.103 +    
 208.104 +    @Override
 208.105 +    public void service(Request request, Response response) throws Exception {
 208.106 +        if ("/test.html".equals(request.getRequestURI())) {
 208.107 +            response.setContentType("text/html");
 208.108 +            final InputStream is = DynamicHTTP.class.getResourceAsStream("test.html");
 208.109 +            copyStream(is, response.getOutputStream(), null);
 208.110 +            return;
 208.111 +        }
 208.112 +        if ("/dynamic".equals(request.getRequestURI())) {
 208.113 +            String mimeType = request.getParameter("mimeType");
 208.114 +            List<String> params = new ArrayList<String>();
 208.115 +            boolean webSocket = false;
 208.116 +            for (int i = 0;; i++) {
 208.117 +                String p = request.getParameter("param" + i);
 208.118 +                if (p == null) {
 208.119 +                    break;
 208.120 +                }
 208.121 +                if ("protocol:ws".equals(p)) {
 208.122 +                    webSocket = true;
 208.123 +                    continue;
 208.124 +                }
 208.125 +                params.add(p);
 208.126 +            }
 208.127 +            final String cnt = request.getParameter("content");
 208.128 +            String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
 208.129 +            ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
 208.130 +            URI url;
 208.131 +            final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
 208.132 +            if (webSocket) {
 208.133 +                url = registerWebSocket(res);
 208.134 +            } else {
 208.135 +                url = registerResource(res);
 208.136 +            }
 208.137 +            response.getWriter().write(url.toString());
 208.138 +            response.getWriter().write("\n");
 208.139 +            return;
 208.140 +        }
 208.141 +
 208.142 +        for (Resource r : resources) {
 208.143 +            if (r.httpPath.equals(request.getRequestURI())) {
 208.144 +                response.setContentType(r.httpType);
 208.145 +                r.httpContent.reset();
 208.146 +                String[] params = null;
 208.147 +                if (r.parameters.length != 0) {
 208.148 +                    params = new String[r.parameters.length];
 208.149 +                    for (int i = 0; i < r.parameters.length; i++) {
 208.150 +                        params[i] = request.getParameter(r.parameters[i]);
 208.151 +                        if (params[i] == null) {
 208.152 +                            if ("http.method".equals(r.parameters[i])) {
 208.153 +                                params[i] = request.getMethod().toString();
 208.154 +                            } else if ("http.requestBody".equals(r.parameters[i])) {
 208.155 +                                Reader rdr = request.getReader();
 208.156 +                                StringBuilder sb = new StringBuilder();
 208.157 +                                for (;;) {
 208.158 +                                    int ch = rdr.read();
 208.159 +                                    if (ch == -1) {
 208.160 +                                        break;
 208.161 +                                    }
 208.162 +                                    sb.append((char) ch);
 208.163 +                                }
 208.164 +                                params[i] = sb.toString();
 208.165 +                            }
 208.166 +                        }
 208.167 +                        if (params[i] == null) {
 208.168 +                            params[i] = "null";
 208.169 +                        }
 208.170 +                    }
 208.171 +                }
 208.172 +
 208.173 +                copyStream(r.httpContent, response.getOutputStream(), null, params);
 208.174 +            }
 208.175 +        }
 208.176 +    }
 208.177 +    
 208.178 +    private URI registerWebSocket(Resource r) {
 208.179 +        WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
 208.180 +        return pageURL("ws", server, r.httpPath);
 208.181 +    }
 208.182 +
 208.183 +    private URI registerResource(Resource r) {
 208.184 +        if (!resources.contains(r)) {
 208.185 +            resources.add(r);
 208.186 +            conf.addHttpHandler(this, r.httpPath);
 208.187 +        }
 208.188 +        return pageURL("http", server, r.httpPath);
 208.189 +    }
 208.190 +    
 208.191 +    private static URI pageURL(String proto, HttpServer server, final String page) {
 208.192 +        NetworkListener listener = server.getListeners().iterator().next();
 208.193 +        int port = listener.getPort();
 208.194 +        try {
 208.195 +            return new URI(proto + "://localhost:" + port + page);
 208.196 +        } catch (URISyntaxException ex) {
 208.197 +            throw new IllegalStateException(ex);
 208.198 +        }
 208.199 +    }
 208.200 +    
 208.201 +    static final class Resource {
 208.202 +
 208.203 +        final InputStream httpContent;
 208.204 +        final String httpType;
 208.205 +        final String httpPath;
 208.206 +        final String[] parameters;
 208.207 +
 208.208 +        Resource(InputStream httpContent, String httpType, String httpPath,
 208.209 +            String[] parameters) {
 208.210 +            httpContent.mark(Integer.MAX_VALUE);
 208.211 +            this.httpContent = httpContent;
 208.212 +            this.httpType = httpType;
 208.213 +            this.httpPath = httpPath;
 208.214 +            this.parameters = parameters;
 208.215 +        }
 208.216 +    }
 208.217 +
 208.218 +    static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
 208.219 +        for (;;) {
 208.220 +            int ch = is.read();
 208.221 +            if (ch == -1) {
 208.222 +                break;
 208.223 +            }
 208.224 +            if (ch == '$' && params.length > 0) {
 208.225 +                int cnt = is.read() - '0';
 208.226 +                if (baseURL != null && cnt == 'U' - '0') {
 208.227 +                    os.write(baseURL.getBytes("UTF-8"));
 208.228 +                } else {
 208.229 +                    if (cnt >= 0 && cnt < params.length) {
 208.230 +                        os.write(params[cnt].getBytes("UTF-8"));
 208.231 +                    } else {
 208.232 +                        os.write('$');
 208.233 +                        os.write(cnt + '0');
 208.234 +                    }
 208.235 +                }
 208.236 +            } else {
 208.237 +                os.write(ch);
 208.238 +            }
 208.239 +        }
 208.240 +    }
 208.241 +    
 208.242 +    private static class WS extends WebSocketApplication {
 208.243 +        private final Resource r;
 208.244 +
 208.245 +        private WS(Resource r) {
 208.246 +            this.r = r;
 208.247 +        }
 208.248 +
 208.249 +        @Override
 208.250 +        public void onMessage(WebSocket socket, String text) {
 208.251 +            try {
 208.252 +                r.httpContent.reset();
 208.253 +                ByteArrayOutputStream out = new ByteArrayOutputStream();
 208.254 +                copyStream(r.httpContent, out, null, text);
 208.255 +                String s = new String(out.toByteArray(), "UTF-8");
 208.256 +                socket.send(s);
 208.257 +            } catch (IOException ex) {
 208.258 +                LOG.log(Level.WARNING, "Error processing message " + text, ex);
 208.259 +            }
 208.260 +        }
 208.261 +    }
 208.262 +}
   209.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   209.2 +++ b/ko-osgi-test/src/test/java/org/netbeans/html/ko/osgi/test/KOFx.java	Tue Jan 07 08:21:57 2014 +0100
   209.3 @@ -0,0 +1,118 @@
   209.4 +/**
   209.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   209.6 + *
   209.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   209.8 + *
   209.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  209.10 + * Other names may be trademarks of their respective owners.
  209.11 + *
  209.12 + * The contents of this file are subject to the terms of either the GNU
  209.13 + * General Public License Version 2 only ("GPL") or the Common
  209.14 + * Development and Distribution License("CDDL") (collectively, the
  209.15 + * "License"). You may not use this file except in compliance with the
  209.16 + * License. You can obtain a copy of the License at
  209.17 + * http://www.netbeans.org/cddl-gplv2.html
  209.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  209.19 + * specific language governing permissions and limitations under the
  209.20 + * License.  When distributing the software, include this License Header
  209.21 + * Notice in each file and include the License file at
  209.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  209.23 + * particular file as subject to the "Classpath" exception as provided
  209.24 + * by Oracle in the GPL Version 2 section of the License file that
  209.25 + * accompanied this code. If applicable, add the following below the
  209.26 + * License Header, with the fields enclosed by brackets [] replaced by
  209.27 + * your own identifying information:
  209.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  209.29 + *
  209.30 + * Contributor(s):
  209.31 + *
  209.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  209.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  209.34 + *
  209.35 + * If you wish your version of this file to be governed by only the CDDL
  209.36 + * or only the GPL Version 2, indicate your decision by adding
  209.37 + * "[Contributor] elects to include this software in this distribution
  209.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  209.39 + * single choice of license, a recipient has the option to distribute
  209.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  209.41 + * to extend the choice of license to its licensees as provided above.
  209.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  209.43 + * Version 2 license, then the option applies only if the new code is
  209.44 + * made subject to such option by the copyright holder.
  209.45 + */
  209.46 +package org.netbeans.html.ko.osgi.test;
  209.47 +
  209.48 +import java.io.Closeable;
  209.49 +import java.lang.reflect.InvocationTargetException;
  209.50 +import java.lang.reflect.Method;
  209.51 +import javafx.application.Platform;
  209.52 +import org.apidesign.html.boot.spi.Fn;
  209.53 +import org.testng.ITest;
  209.54 +import org.testng.annotations.Test;
  209.55 +
  209.56 +/**
  209.57 + *
  209.58 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  209.59 + */
  209.60 +public final class KOFx implements ITest, Runnable {
  209.61 +    private final Object p;
  209.62 +    private final Method m;
  209.63 +    private Object result;
  209.64 +    private Object inst;
  209.65 +    private int count;
  209.66 +
  209.67 +    KOFx(Object p, Method m) {
  209.68 +        this.p = p;
  209.69 +        this.m = m;
  209.70 +    }
  209.71 +
  209.72 +    @Override
  209.73 +    public String getTestName() {
  209.74 +        return m.getName();
  209.75 +    }
  209.76 +
  209.77 +    @Test
  209.78 +    public synchronized void executeTest() throws Exception {
  209.79 +        if (result == null) {
  209.80 +            Platform.runLater(this);
  209.81 +            wait();
  209.82 +        }
  209.83 +        if (result instanceof Exception) {
  209.84 +            throw (Exception)result;
  209.85 +        }
  209.86 +        if (result instanceof Error) {
  209.87 +            throw (Error)result;
  209.88 +        }
  209.89 +    }
  209.90 +
  209.91 +    @Override
  209.92 +    public synchronized void run() {
  209.93 +        boolean notify = true;
  209.94 +        try (Closeable a = KnockoutEquinoxIT.activateInOSGi(p)) {
  209.95 +            if (inst == null) {
  209.96 +                inst = m.getDeclaringClass().newInstance();
  209.97 +            }
  209.98 +            result = m.invoke(inst);
  209.99 +            if (result == null) {
 209.100 +                result = this;
 209.101 +            }
 209.102 +        } catch (InvocationTargetException ex) {
 209.103 +            Throwable r = ex.getTargetException();
 209.104 +            if (r instanceof InterruptedException) {
 209.105 +                if (count++ < 10000) {
 209.106 +                    notify = false;
 209.107 +                    Platform.runLater(this);
 209.108 +                    return;
 209.109 +                }
 209.110 +            }
 209.111 +            result = r;
 209.112 +        } catch (Exception ex) {
 209.113 +            result = ex;
 209.114 +        } finally {
 209.115 +            if (notify) {
 209.116 +                notifyAll();
 209.117 +            }
 209.118 +        }
 209.119 +    }
 209.120 +    
 209.121 +}
   210.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   210.2 +++ b/ko-osgi-test/src/test/java/org/netbeans/html/ko/osgi/test/KnockoutEquinoxIT.java	Tue Jan 07 08:21:57 2014 +0100
   210.3 @@ -0,0 +1,243 @@
   210.4 +/**
   210.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   210.6 + *
   210.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   210.8 + *
   210.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  210.10 + * Other names may be trademarks of their respective owners.
  210.11 + *
  210.12 + * The contents of this file are subject to the terms of either the GNU
  210.13 + * General Public License Version 2 only ("GPL") or the Common
  210.14 + * Development and Distribution License("CDDL") (collectively, the
  210.15 + * "License"). You may not use this file except in compliance with the
  210.16 + * License. You can obtain a copy of the License at
  210.17 + * http://www.netbeans.org/cddl-gplv2.html
  210.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  210.19 + * specific language governing permissions and limitations under the
  210.20 + * License.  When distributing the software, include this License Header
  210.21 + * Notice in each file and include the License file at
  210.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  210.23 + * particular file as subject to the "Classpath" exception as provided
  210.24 + * by Oracle in the GPL Version 2 section of the License file that
  210.25 + * accompanied this code. If applicable, add the following below the
  210.26 + * License Header, with the fields enclosed by brackets [] replaced by
  210.27 + * your own identifying information:
  210.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  210.29 + *
  210.30 + * Contributor(s):
  210.31 + *
  210.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  210.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  210.34 + *
  210.35 + * If you wish your version of this file to be governed by only the CDDL
  210.36 + * or only the GPL Version 2, indicate your decision by adding
  210.37 + * "[Contributor] elects to include this software in this distribution
  210.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  210.39 + * single choice of license, a recipient has the option to distribute
  210.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  210.41 + * to extend the choice of license to its licensees as provided above.
  210.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  210.43 + * Version 2 license, then the option applies only if the new code is
  210.44 + * made subject to such option by the copyright holder.
  210.45 + */
  210.46 +package org.netbeans.html.ko.osgi.test;
  210.47 +
  210.48 +import java.io.Closeable;
  210.49 +import java.io.File;
  210.50 +import java.io.IOException;
  210.51 +import java.lang.annotation.Annotation;
  210.52 +import java.lang.reflect.Method;
  210.53 +import java.net.URI;
  210.54 +import java.util.ArrayList;
  210.55 +import java.util.HashMap;
  210.56 +import java.util.List;
  210.57 +import java.util.Map;
  210.58 +import java.util.ServiceLoader;
  210.59 +import java.util.concurrent.Callable;
  210.60 +import java.util.jar.JarFile;
  210.61 +import java.util.logging.Level;
  210.62 +import java.util.logging.Logger;
  210.63 +import org.apidesign.html.boot.spi.Fn;
  210.64 +import org.apidesign.html.json.tck.KOTest;
  210.65 +import org.apidesign.html.json.tck.KnockoutTCK;
  210.66 +import org.osgi.framework.Bundle;
  210.67 +import org.osgi.framework.BundleException;
  210.68 +import org.osgi.framework.Constants;
  210.69 +import org.osgi.framework.launch.Framework;
  210.70 +import org.osgi.framework.launch.FrameworkFactory;
  210.71 +import static org.testng.Assert.assertNotNull;
  210.72 +import static org.testng.Assert.fail;
  210.73 +import org.testng.annotations.AfterClass;
  210.74 +import org.testng.annotations.Factory;
  210.75 +
  210.76 +/**
  210.77 + *
  210.78 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  210.79 + */
  210.80 +public class KnockoutEquinoxIT {
  210.81 +    private static final Logger LOG = Logger.getLogger(KnockoutEquinoxIT.class.getName());
  210.82 +    private static Framework framework;
  210.83 +    private static File dir;
  210.84 +    static Framework framework() throws Exception {
  210.85 +        if (framework != null) {
  210.86 +            return framework;
  210.87 +        }
  210.88 +        for (FrameworkFactory ff : ServiceLoader.load(FrameworkFactory.class)) {
  210.89 +            
  210.90 +            String basedir = System.getProperty("basedir");
  210.91 +            assertNotNull("basedir preperty provided", basedir);
  210.92 +            File target = new File(basedir, "target");
  210.93 +            dir = new File(target, "osgi");
  210.94 +            dir.mkdirs();
  210.95 +            
  210.96 +            Map<String,String> config = new HashMap<>();
  210.97 +            config.put(Constants.FRAMEWORK_STORAGE, dir.getPath());
  210.98 +            config.put(Constants.FRAMEWORK_STORAGE_CLEAN, "true");
  210.99 +            config.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, "sun.misc,"
 210.100 +                + "javafx.application,"
 210.101 +                + "javafx.beans.property,"
 210.102 +                + "javafx.beans.value,"
 210.103 +                + "javafx.collections,"
 210.104 +                + "javafx.concurrent,"
 210.105 +                + "javafx.event,"
 210.106 +                + "javafx.geometry,"
 210.107 +                + "javafx.scene,"
 210.108 +                + "javafx.scene.control,"
 210.109 +                + "javafx.scene.layout,"
 210.110 +                + "javafx.scene.text,"
 210.111 +                + "javafx.scene.web,"
 210.112 +                + "javafx.stage,"
 210.113 +                + "javafx.util,"
 210.114 +                + "netscape.javascript"
 210.115 +            );
 210.116 +            config.put("osgi.hook.configurators.include", "org.netbeans.html.equinox.agentclass.AgentHook");
 210.117 +            framework = ff.newFramework(config);
 210.118 +            framework.init();
 210.119 +            loadClassPathBundles(framework);
 210.120 +            framework.start();
 210.121 +            for (Bundle b : framework.getBundleContext().getBundles()) {
 210.122 +                try {
 210.123 +                    if (b.getSymbolicName().contains("equinox-agentclass-hook")) {
 210.124 +                        continue;
 210.125 +                    }
 210.126 +                    if (b.getSymbolicName().contains("grizzly.websockets-server")) {
 210.127 +                        continue;
 210.128 +                    }
 210.129 +                    b.start();
 210.130 +                    LOG.log(Level.INFO, "Started {0}", b.getSymbolicName());
 210.131 +                } catch (BundleException ex) {
 210.132 +                    LOG.log(Level.WARNING, "Cannot start bundle " + b.getSymbolicName(), ex);
 210.133 +                }
 210.134 +            }
 210.135 +            return framework;
 210.136 +        }
 210.137 +        fail("No OSGi framework in the path");
 210.138 +        return null;
 210.139 +    }
 210.140 +    
 210.141 +    @AfterClass public static void cleanUp() throws Exception {
 210.142 +        if (framework != null) framework.stop();
 210.143 +        clearUpDir(dir);
 210.144 +    }
 210.145 +    private static void clearUpDir(File dir) {
 210.146 +        if (dir.isDirectory()) {
 210.147 +            for (File f : dir.listFiles()) {
 210.148 +                clearUpDir(f);
 210.149 +            }
 210.150 +        }
 210.151 +        dir.delete();
 210.152 +    }
 210.153 +    
 210.154 +    
 210.155 +
 210.156 +    private static void loadClassPathBundles(Framework f) throws IOException, BundleException {
 210.157 +        for (String jar : System.getProperty("java.class.path").split(File.pathSeparator)) {
 210.158 +            File file = new File(jar);
 210.159 +            if (!file.isFile()) {
 210.160 +                LOG.info("Not loading " + file);
 210.161 +                continue;
 210.162 +            }
 210.163 +            JarFile jf = new JarFile(file);
 210.164 +            final String name = jf.getManifest().getMainAttributes().getValue("Bundle-SymbolicName");
 210.165 +            jf.close();
 210.166 +            if (name != null) {
 210.167 +                if (name.contains("org.eclipse.osgi")) {
 210.168 +                    continue;
 210.169 +                }
 210.170 +                if (name.contains("testng")) {
 210.171 +                    continue;
 210.172 +                }
 210.173 +                final String path = "reference:" + file.toURI().toString();
 210.174 +                try {
 210.175 +                    Bundle b = f.getBundleContext().installBundle(path);
 210.176 +                } catch (BundleException ex) {
 210.177 +                    LOG.log(Level.WARNING, "Cannot install " + file, ex);
 210.178 +                }
 210.179 +            }
 210.180 +        }
 210.181 +    }
 210.182 +    
 210.183 +    private static Class<?> loadOSGiClass(Class<?> c) throws Exception {
 210.184 +        return KnockoutEquinoxTCKImpl.loadOSGiClass(c.getName(), KnockoutEquinoxIT.framework().getBundleContext());
 210.185 +    }
 210.186 +    
 210.187 +    private static Class<?> browserClass;
 210.188 +    private static Object browserContext;
 210.189 +    
 210.190 +    @Factory public static Object[] compatibilityTests() throws Exception {
 210.191 +        Class<?> tck = loadOSGiClass(KnockoutTCK.class);
 210.192 +        Class<?> peer = loadOSGiClass(KnockoutEquinoxTCKImpl.class);
 210.193 +        // initialize the TCK
 210.194 +        Callable<Class[]> inst = (Callable<Class[]>) peer.newInstance();
 210.195 +        
 210.196 +        Class[] arr = inst.call();
 210.197 +        for (int i = 0; i < arr.length; i++) {
 210.198 +            if (arr[i].getClassLoader() == ClassLoader.getSystemClassLoader()) {
 210.199 +                fail("Should be an OSGi class: " + arr[i]);
 210.200 +            }
 210.201 +        }
 210.202 +        
 210.203 +        URI uri = DynamicHTTP.initServer();
 210.204 +
 210.205 +        Method start = peer.getMethod("start", URI.class);
 210.206 +        start.invoke(null, uri);
 210.207 +        
 210.208 +        ClassLoader l = getClassLoader();
 210.209 +        List<Object> res = new ArrayList<Object>();
 210.210 +        for (int i = 0; i < arr.length; i++) {
 210.211 +            seekKOTests(arr[i], res);
 210.212 +        }
 210.213 +        return res.toArray();
 210.214 +    }
 210.215 +
 210.216 +    private static void seekKOTests(Class<?> c, List<Object> res) throws SecurityException, ClassNotFoundException {
 210.217 +        Class<? extends Annotation> koTest =
 210.218 +            c.getClassLoader().loadClass(KOTest.class.getName()).
 210.219 +            asSubclass(Annotation.class);
 210.220 +        for (Method m : c.getMethods()) {
 210.221 +            if (m.getAnnotation(koTest) != null) {
 210.222 +                res.add(new KOFx(browserContext, m));
 210.223 +            }
 210.224 +        }
 210.225 +    }
 210.226 +
 210.227 +    static synchronized ClassLoader getClassLoader() throws InterruptedException {
 210.228 +        while (browserClass == null) {
 210.229 +            KnockoutEquinoxIT.class.wait();
 210.230 +        }
 210.231 +        return browserClass.getClassLoader();
 210.232 +    }
 210.233 +    
 210.234 +    public static synchronized void initialized(Class<?> browserCls, Object presenter) throws Exception {
 210.235 +        browserClass = browserCls;
 210.236 +        browserContext = presenter;
 210.237 +        KnockoutEquinoxIT.class.notifyAll();
 210.238 +    }
 210.239 +
 210.240 +    static Closeable activateInOSGi(Object presenter) throws Exception {
 210.241 +        Class<?> presenterClass = loadOSGiClass(Fn.Presenter.class);
 210.242 +        Class<?> fnClass = loadOSGiClass(Fn.class);
 210.243 +        Method m = fnClass.getMethod("activate", presenterClass);
 210.244 +        return (Closeable) m.invoke(null, presenter);
 210.245 +    }
 210.246 +}
   211.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   211.2 +++ b/ko-osgi-test/src/test/resources/org/netbeans/html/ko/osgi/test/test.html	Tue Jan 07 08:21:57 2014 +0100
   211.3 @@ -0,0 +1,56 @@
   211.4 +<!--
   211.5 +
   211.6 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   211.7 +
   211.8 +    Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   211.9 +
  211.10 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  211.11 +    Other names may be trademarks of their respective owners.
  211.12 +
  211.13 +    The contents of this file are subject to the terms of either the GNU
  211.14 +    General Public License Version 2 only ("GPL") or the Common
  211.15 +    Development and Distribution License("CDDL") (collectively, the
  211.16 +    "License"). You may not use this file except in compliance with the
  211.17 +    License. You can obtain a copy of the License at
  211.18 +    http://www.netbeans.org/cddl-gplv2.html
  211.19 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  211.20 +    specific language governing permissions and limitations under the
  211.21 +    License.  When distributing the software, include this License Header
  211.22 +    Notice in each file and include the License file at
  211.23 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  211.24 +    particular file as subject to the "Classpath" exception as provided
  211.25 +    by Oracle in the GPL Version 2 section of the License file that
  211.26 +    accompanied this code. If applicable, add the following below the
  211.27 +    License Header, with the fields enclosed by brackets [] replaced by
  211.28 +    your own identifying information:
  211.29 +    "Portions Copyrighted [year] [name of copyright owner]"
  211.30 +
  211.31 +    Contributor(s):
  211.32 +
  211.33 +    The Original Software is NetBeans. The Initial Developer of the Original
  211.34 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  211.35 +
  211.36 +    If you wish your version of this file to be governed by only the CDDL
  211.37 +    or only the GPL Version 2, indicate your decision by adding
  211.38 +    "[Contributor] elects to include this software in this distribution
  211.39 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
  211.40 +    single choice of license, a recipient has the option to distribute
  211.41 +    your version of this file under either the CDDL, the GPL Version 2 or
  211.42 +    to extend the choice of license to its licensees as provided above.
  211.43 +    However, if you add GPL Version 2 code and therefore, elected the GPL
  211.44 +    Version 2 license, then the option applies only if the new code is
  211.45 +    made subject to such option by the copyright holder.
  211.46 +
  211.47 +-->
  211.48 +<!DOCTYPE html>
  211.49 +<html>
  211.50 +    <head>
  211.51 +        <title>Knockout.fx Execution Harness</title>
  211.52 +        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  211.53 +        <meta name="viewport" content="width=device-width">
  211.54 +    </head>
  211.55 +    <body>
  211.56 +        <h1>Knockout.fx Execution Harness</h1>
  211.57 +    </body>
  211.58 +    <script></script>
  211.59 +</html>
   212.1 --- a/ko-ws-tyrus/pom.xml	Thu Dec 19 17:11:01 2013 +0100
   212.2 +++ b/ko-ws-tyrus/pom.xml	Tue Jan 07 08:21:57 2014 +0100
   212.3 @@ -2,11 +2,11 @@
   212.4  <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">
   212.5    <modelVersion>4.0.0</modelVersion>
   212.6    <parent>
   212.7 -    <groupId>org.apidesign</groupId>
   212.8 -    <artifactId>html</artifactId>
   212.9 +    <groupId>org.netbeans.html</groupId>
  212.10 +    <artifactId>pom</artifactId>
  212.11      <version>0.7-SNAPSHOT</version>
  212.12    </parent>
  212.13 -  <groupId>org.apidesign.html</groupId>
  212.14 +  <groupId>org.netbeans.html</groupId>
  212.15    <artifactId>ko-ws-tyrus</artifactId>
  212.16    <version>0.7-SNAPSHOT</version>
  212.17    <packaging>bundle</packaging>
  212.18 @@ -38,6 +38,7 @@
  212.19      </build>
  212.20      <properties>
  212.21      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  212.22 +    <bundleSymbolicName>org.netbeans.html.ko-ws-tyrus</bundleSymbolicName>
  212.23    </properties>
  212.24    <dependencies>
  212.25      <!-- compile only deps -->
  212.26 @@ -126,7 +127,7 @@
  212.27      </dependency>
  212.28      <dependency>
  212.29          <groupId>${project.groupId}</groupId>
  212.30 -        <artifactId>boot-fx</artifactId>
  212.31 +        <artifactId>net.java.html.boot.fx</artifactId>
  212.32          <version>${project.version}</version>
  212.33          <scope>test</scope>
  212.34      </dependency>
   213.1 --- a/ko-ws-tyrus/src/main/java/org/apidesign/html/wstyrus/TyrusContext.java	Thu Dec 19 17:11:01 2013 +0100
   213.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   213.3 @@ -1,168 +0,0 @@
   213.4 -/**
   213.5 - * HTML via Java(tm) Language Bindings
   213.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   213.7 - *
   213.8 - * This program is free software: you can redistribute it and/or modify
   213.9 - * it under the terms of the GNU General Public License as published by
  213.10 - * the Free Software Foundation, version 2 of the License.
  213.11 - *
  213.12 - * This program is distributed in the hope that it will be useful,
  213.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  213.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  213.15 - * GNU General Public License for more details. apidesign.org
  213.16 - * designates this particular file as subject to the
  213.17 - * "Classpath" exception as provided by apidesign.org
  213.18 - * in the License file that accompanied this code.
  213.19 - *
  213.20 - * You should have received a copy of the GNU General Public License
  213.21 - * along with this program. Look for COPYING file in the top folder.
  213.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  213.23 - */
  213.24 -package org.apidesign.html.wstyrus;
  213.25 -
  213.26 -import java.io.IOException;
  213.27 -import java.net.URI;
  213.28 -import java.net.URISyntaxException;
  213.29 -import java.util.Iterator;
  213.30 -import javax.websocket.ClientEndpoint;
  213.31 -import javax.websocket.ContainerProvider;
  213.32 -import javax.websocket.DeploymentException;
  213.33 -import javax.websocket.OnClose;
  213.34 -import javax.websocket.OnError;
  213.35 -import javax.websocket.OnMessage;
  213.36 -import javax.websocket.OnOpen;
  213.37 -import javax.websocket.Session;
  213.38 -import javax.websocket.WebSocketContainer;
  213.39 -import net.java.html.json.OnReceive;
  213.40 -import org.apidesign.html.context.spi.Contexts;
  213.41 -import org.apidesign.html.json.spi.JSONCall;
  213.42 -import org.apidesign.html.json.spi.WSTransfer;
  213.43 -import org.apidesign.html.wstyrus.TyrusContext.Comm;
  213.44 -import org.json.JSONArray;
  213.45 -import org.json.JSONException;
  213.46 -import org.json.JSONObject;
  213.47 -import org.json.JSONTokener;
  213.48 -import org.openide.util.lookup.ServiceProvider;
  213.49 -
  213.50 -/** This is an implementation module that provides support for
  213.51 - * WebSocket protocol for {@link OnReceive} communication end point for
  213.52 - * JDK7.
  213.53 - * <p>
  213.54 - * Don't deal with this module directly, rather use the 
  213.55 - * {@link OnReceive @OnReceive(url="ws://...", ...)} API to establish your
  213.56 - * WebSocket connection.
  213.57 - * <p>
  213.58 - * There is no need to include this module in your application if you are
  213.59 - * running on JDK8. JDK8 WebView provides its own implementation of the
  213.60 - * WebSocket API based on WebSocket object inside a browser. This is included
  213.61 - * in the <code>org.apidesign.html:ko-fx:0.5</code> module.
  213.62 - *
  213.63 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  213.64 - */
  213.65 -@ServiceProvider(service = Contexts.Provider.class)
  213.66 -public final class TyrusContext implements Contexts.Provider, WSTransfer<Comm> {
  213.67 -    @Override
  213.68 -    public void fillContext(Contexts.Builder context, Class<?> requestor) {
  213.69 -        // default WebSocket transfer implementation is registered
  213.70 -        // in ko-fx module with 100, provide this one as a fallback only
  213.71 -        context.register(WSTransfer.class, this, 1000);
  213.72 -    }
  213.73 -
  213.74 -    @Override
  213.75 -    public Comm open(String url, JSONCall callback) {
  213.76 -        try {
  213.77 -            return new Comm(new URI(url), callback);
  213.78 -        } catch (URISyntaxException ex) {
  213.79 -            throw new IllegalStateException(ex);
  213.80 -        }
  213.81 -    }
  213.82 -
  213.83 -    @Override
  213.84 -    public void send(Comm socket, JSONCall data) {
  213.85 -        socket.session.getAsyncRemote().sendText(data.getMessage());
  213.86 -    }
  213.87 -
  213.88 -    @Override
  213.89 -    public void close(Comm socket) {
  213.90 -        try {
  213.91 -            final Session s = socket.session;
  213.92 -            if (s != null) {
  213.93 -                s.close();
  213.94 -            }
  213.95 -        } catch (IOException ex) {
  213.96 -            socket.callback.notifyError(ex);
  213.97 -        }
  213.98 -    }
  213.99 -    
 213.100 -    /** Implementation class in an implementation. Represents a {@link ClientEndpoint} of the
 213.101 -     * WebSocket channel. You are unlikely to get on hold of it.
 213.102 -     */
 213.103 -    @ClientEndpoint
 213.104 -    public static final class Comm {
 213.105 -        private final JSONCall callback;
 213.106 -        private Session session;
 213.107 -
 213.108 -        Comm(final URI url, JSONCall callback) {
 213.109 -            this.callback = callback;
 213.110 -            try {
 213.111 -                final WebSocketContainer c = ContainerProvider.getWebSocketContainer();
 213.112 -                c.connectToServer(Comm.this, url);
 213.113 -            } catch (DeploymentException | IOException ex) {
 213.114 -                wasAnError(ex);
 213.115 -            }
 213.116 -        }
 213.117 -
 213.118 -        @OnOpen
 213.119 -        public synchronized void open(Session s) {
 213.120 -            this.session = s;
 213.121 -            callback.notifySuccess(null);
 213.122 -        }
 213.123 -
 213.124 -        @OnClose
 213.125 -        public void close() {
 213.126 -            this.session = null;
 213.127 -            callback.notifyError(null);
 213.128 -        }
 213.129 -
 213.130 -        @OnMessage
 213.131 -        public void message(final String orig, Session s) {
 213.132 -            Object json;
 213.133 -            String data = orig.trim();
 213.134 -            try {
 213.135 -                JSONTokener tok = new JSONTokener(data);
 213.136 -                Object obj = data.startsWith("[") ? new JSONArray(tok) : new JSONObject(tok);
 213.137 -                json = convertToArray(obj);
 213.138 -            } catch (JSONException ex) {
 213.139 -                json = data;
 213.140 -            }
 213.141 -            callback.notifySuccess(json);
 213.142 -        }
 213.143 -
 213.144 -        @OnError
 213.145 -        public void wasAnError(Throwable t) {
 213.146 -            callback.notifyError(t);
 213.147 -        }
 213.148 -
 213.149 -        static Object convertToArray(Object o) throws JSONException {
 213.150 -            if (o instanceof JSONArray) {
 213.151 -                JSONArray ja = (JSONArray) o;
 213.152 -                Object[] arr = new Object[ja.length()];
 213.153 -                for (int i = 0; i < arr.length; i++) {
 213.154 -                    arr[i] = convertToArray(ja.get(i));
 213.155 -                }
 213.156 -                return arr;
 213.157 -            } else if (o instanceof JSONObject) {
 213.158 -                JSONObject obj = (JSONObject) o;
 213.159 -                Iterator it = obj.keys();
 213.160 -                while (it.hasNext()) {
 213.161 -                    String key = (String) it.next();
 213.162 -                    obj.put(key, convertToArray(obj.get(key)));
 213.163 -                }
 213.164 -                return obj;
 213.165 -            } else {
 213.166 -                return o;
 213.167 -            }
 213.168 -        }
 213.169 -        
 213.170 -    } // end of Comm
 213.171 -}
   214.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   214.2 +++ b/ko-ws-tyrus/src/main/java/org/netbeans/html/wstyrus/TyrusContext.java	Tue Jan 07 08:21:57 2014 +0100
   214.3 @@ -0,0 +1,190 @@
   214.4 +/**
   214.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   214.6 + *
   214.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   214.8 + *
   214.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  214.10 + * Other names may be trademarks of their respective owners.
  214.11 + *
  214.12 + * The contents of this file are subject to the terms of either the GNU
  214.13 + * General Public License Version 2 only ("GPL") or the Common
  214.14 + * Development and Distribution License("CDDL") (collectively, the
  214.15 + * "License"). You may not use this file except in compliance with the
  214.16 + * License. You can obtain a copy of the License at
  214.17 + * http://www.netbeans.org/cddl-gplv2.html
  214.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  214.19 + * specific language governing permissions and limitations under the
  214.20 + * License.  When distributing the software, include this License Header
  214.21 + * Notice in each file and include the License file at
  214.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  214.23 + * particular file as subject to the "Classpath" exception as provided
  214.24 + * by Oracle in the GPL Version 2 section of the License file that
  214.25 + * accompanied this code. If applicable, add the following below the
  214.26 + * License Header, with the fields enclosed by brackets [] replaced by
  214.27 + * your own identifying information:
  214.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  214.29 + *
  214.30 + * Contributor(s):
  214.31 + *
  214.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  214.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  214.34 + *
  214.35 + * If you wish your version of this file to be governed by only the CDDL
  214.36 + * or only the GPL Version 2, indicate your decision by adding
  214.37 + * "[Contributor] elects to include this software in this distribution
  214.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  214.39 + * single choice of license, a recipient has the option to distribute
  214.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  214.41 + * to extend the choice of license to its licensees as provided above.
  214.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  214.43 + * Version 2 license, then the option applies only if the new code is
  214.44 + * made subject to such option by the copyright holder.
  214.45 + */
  214.46 +package org.netbeans.html.wstyrus;
  214.47 +
  214.48 +import java.io.IOException;
  214.49 +import java.net.URI;
  214.50 +import java.net.URISyntaxException;
  214.51 +import java.util.Iterator;
  214.52 +import javax.websocket.ClientEndpoint;
  214.53 +import javax.websocket.ContainerProvider;
  214.54 +import javax.websocket.DeploymentException;
  214.55 +import javax.websocket.OnClose;
  214.56 +import javax.websocket.OnError;
  214.57 +import javax.websocket.OnMessage;
  214.58 +import javax.websocket.OnOpen;
  214.59 +import javax.websocket.Session;
  214.60 +import javax.websocket.WebSocketContainer;
  214.61 +import net.java.html.json.OnReceive;
  214.62 +import org.apidesign.html.context.spi.Contexts;
  214.63 +import org.apidesign.html.json.spi.JSONCall;
  214.64 +import org.apidesign.html.json.spi.WSTransfer;
  214.65 +import org.netbeans.html.wstyrus.TyrusContext.Comm;
  214.66 +import org.json.JSONArray;
  214.67 +import org.json.JSONException;
  214.68 +import org.json.JSONObject;
  214.69 +import org.json.JSONTokener;
  214.70 +import org.openide.util.lookup.ServiceProvider;
  214.71 +
  214.72 +/** This is an implementation module that provides support for
  214.73 + * WebSocket protocol for {@link OnReceive} communication end point for
  214.74 + * JDK7.
  214.75 + * <p>
  214.76 + * Don't deal with this module directly, rather use the 
  214.77 + * {@link OnReceive @OnReceive(url="ws://...", ...)} API to establish your
  214.78 + * WebSocket connection.
  214.79 + * <p>
  214.80 + * There is no need to include this module in your application if you are
  214.81 + * running on JDK8. JDK8 WebView provides its own implementation of the
  214.82 + * WebSocket API based on WebSocket object inside a browser. This is included
  214.83 + * in the <code>org.apidesign.html:ko-fx:0.5</code> module.
  214.84 + *
  214.85 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  214.86 + */
  214.87 +@ServiceProvider(service = Contexts.Provider.class)
  214.88 +public final class TyrusContext implements Contexts.Provider, WSTransfer<Comm> {
  214.89 +    @Override
  214.90 +    public void fillContext(Contexts.Builder context, Class<?> requestor) {
  214.91 +        // default WebSocket transfer implementation is registered
  214.92 +        // in ko-fx module with 100, provide this one as a fallback only
  214.93 +        context.register(WSTransfer.class, this, 1000);
  214.94 +    }
  214.95 +
  214.96 +    @Override
  214.97 +    public Comm open(String url, JSONCall callback) {
  214.98 +        try {
  214.99 +            return new Comm(new URI(url), callback);
 214.100 +        } catch (URISyntaxException ex) {
 214.101 +            throw new IllegalStateException(ex);
 214.102 +        }
 214.103 +    }
 214.104 +
 214.105 +    @Override
 214.106 +    public void send(Comm socket, JSONCall data) {
 214.107 +        socket.session.getAsyncRemote().sendText(data.getMessage());
 214.108 +    }
 214.109 +
 214.110 +    @Override
 214.111 +    public void close(Comm socket) {
 214.112 +        try {
 214.113 +            final Session s = socket.session;
 214.114 +            if (s != null) {
 214.115 +                s.close();
 214.116 +            }
 214.117 +        } catch (IOException ex) {
 214.118 +            socket.callback.notifyError(ex);
 214.119 +        }
 214.120 +    }
 214.121 +    
 214.122 +    /** Implementation class in an implementation. Represents a {@link ClientEndpoint} of the
 214.123 +     * WebSocket channel. You are unlikely to get on hold of it.
 214.124 +     */
 214.125 +    @ClientEndpoint
 214.126 +    public static final class Comm {
 214.127 +        private final JSONCall callback;
 214.128 +        private Session session;
 214.129 +
 214.130 +        Comm(final URI url, JSONCall callback) {
 214.131 +            this.callback = callback;
 214.132 +            try {
 214.133 +                final WebSocketContainer c = ContainerProvider.getWebSocketContainer();
 214.134 +                c.connectToServer(Comm.this, url);
 214.135 +            } catch (DeploymentException | IOException ex) {
 214.136 +                wasAnError(ex);
 214.137 +            }
 214.138 +        }
 214.139 +
 214.140 +        @OnOpen
 214.141 +        public synchronized void open(Session s) {
 214.142 +            this.session = s;
 214.143 +            callback.notifySuccess(null);
 214.144 +        }
 214.145 +
 214.146 +        @OnClose
 214.147 +        public void close() {
 214.148 +            this.session = null;
 214.149 +            callback.notifyError(null);
 214.150 +        }
 214.151 +
 214.152 +        @OnMessage
 214.153 +        public void message(final String orig, Session s) {
 214.154 +            Object json;
 214.155 +            String data = orig.trim();
 214.156 +            try {
 214.157 +                JSONTokener tok = new JSONTokener(data);
 214.158 +                Object obj = data.startsWith("[") ? new JSONArray(tok) : new JSONObject(tok);
 214.159 +                json = convertToArray(obj);
 214.160 +            } catch (JSONException ex) {
 214.161 +                json = data;
 214.162 +            }
 214.163 +            callback.notifySuccess(json);
 214.164 +        }
 214.165 +
 214.166 +        @OnError
 214.167 +        public void wasAnError(Throwable t) {
 214.168 +            callback.notifyError(t);
 214.169 +        }
 214.170 +
 214.171 +        static Object convertToArray(Object o) throws JSONException {
 214.172 +            if (o instanceof JSONArray) {
 214.173 +                JSONArray ja = (JSONArray) o;
 214.174 +                Object[] arr = new Object[ja.length()];
 214.175 +                for (int i = 0; i < arr.length; i++) {
 214.176 +                    arr[i] = convertToArray(ja.get(i));
 214.177 +                }
 214.178 +                return arr;
 214.179 +            } else if (o instanceof JSONObject) {
 214.180 +                JSONObject obj = (JSONObject) o;
 214.181 +                Iterator it = obj.keys();
 214.182 +                while (it.hasNext()) {
 214.183 +                    String key = (String) it.next();
 214.184 +                    obj.put(key, convertToArray(obj.get(key)));
 214.185 +                }
 214.186 +                return obj;
 214.187 +            } else {
 214.188 +                return o;
 214.189 +            }
 214.190 +        }
 214.191 +        
 214.192 +    } // end of Comm
 214.193 +}
   215.1 --- a/ko-ws-tyrus/src/test/java/org/apidesign/html/wstyrus/TyrusDynamicHTTP.java	Thu Dec 19 17:11:01 2013 +0100
   215.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   215.3 @@ -1,238 +0,0 @@
   215.4 -/**
   215.5 - * HTML via Java(tm) Language Bindings
   215.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   215.7 - *
   215.8 - * This program is free software: you can redistribute it and/or modify
   215.9 - * it under the terms of the GNU General Public License as published by
  215.10 - * the Free Software Foundation, version 2 of the License.
  215.11 - *
  215.12 - * This program is distributed in the hope that it will be useful,
  215.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  215.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  215.15 - * GNU General Public License for more details. apidesign.org
  215.16 - * designates this particular file as subject to the
  215.17 - * "Classpath" exception as provided by apidesign.org
  215.18 - * in the License file that accompanied this code.
  215.19 - *
  215.20 - * You should have received a copy of the GNU General Public License
  215.21 - * along with this program. Look for COPYING file in the top folder.
  215.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  215.23 - */
  215.24 -package org.apidesign.html.wstyrus;
  215.25 -
  215.26 -import java.io.ByteArrayInputStream;
  215.27 -import java.io.ByteArrayOutputStream;
  215.28 -import java.io.IOException;
  215.29 -import java.io.InputStream;
  215.30 -import java.io.OutputStream;
  215.31 -import java.io.Reader;
  215.32 -import java.net.URI;
  215.33 -import java.net.URISyntaxException;
  215.34 -import java.util.ArrayList;
  215.35 -import java.util.List;
  215.36 -import java.util.logging.Level;
  215.37 -import java.util.logging.Logger;
  215.38 -import org.glassfish.grizzly.PortRange;
  215.39 -import org.glassfish.grizzly.http.server.HttpHandler;
  215.40 -import org.glassfish.grizzly.http.server.HttpServer;
  215.41 -import org.glassfish.grizzly.http.server.NetworkListener;
  215.42 -import org.glassfish.grizzly.http.server.Request;
  215.43 -import org.glassfish.grizzly.http.server.Response;
  215.44 -import org.glassfish.grizzly.http.server.ServerConfiguration;
  215.45 -import org.glassfish.grizzly.websockets.WebSocket;
  215.46 -import org.glassfish.grizzly.websockets.WebSocketAddOn;
  215.47 -import org.glassfish.grizzly.websockets.WebSocketApplication;
  215.48 -import org.glassfish.grizzly.websockets.WebSocketEngine;
  215.49 -
  215.50 -/**
  215.51 - *
  215.52 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  215.53 - */
  215.54 -final class TyrusDynamicHTTP extends HttpHandler {
  215.55 -    private static int resourcesCount;
  215.56 -    private static List<Resource> resources;
  215.57 -    private static ServerConfiguration conf;
  215.58 -    private static HttpServer server;
  215.59 -    
  215.60 -    private TyrusDynamicHTTP() {
  215.61 -    }
  215.62 -    
  215.63 -    static URI initServer() throws Exception {
  215.64 -        server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
  215.65 -        final WebSocketAddOn addon = new WebSocketAddOn();
  215.66 -        for (NetworkListener listener : server.getListeners()) {
  215.67 -            listener.registerAddOn(addon);
  215.68 -        }        
  215.69 -        resources = new ArrayList<Resource>();
  215.70 -
  215.71 -        conf = server.getServerConfiguration();
  215.72 -        final TyrusDynamicHTTP dh = new TyrusDynamicHTTP();
  215.73 -
  215.74 -        conf.addHttpHandler(dh, "/");
  215.75 -        
  215.76 -        server.start();
  215.77 -
  215.78 -        return pageURL("http", server, "/test.html");
  215.79 -    }
  215.80 -    
  215.81 -    @Override
  215.82 -    public void service(Request request, Response response) throws Exception {
  215.83 -        if ("/test.html".equals(request.getRequestURI())) {
  215.84 -            response.setContentType("text/html");
  215.85 -            final InputStream is = TyrusDynamicHTTP.class.getResourceAsStream("test.html");
  215.86 -            copyStream(is, response.getOutputStream(), null);
  215.87 -            return;
  215.88 -        }
  215.89 -        if ("/dynamic".equals(request.getRequestURI())) {
  215.90 -            String mimeType = request.getParameter("mimeType");
  215.91 -            List<String> params = new ArrayList<String>();
  215.92 -            boolean webSocket = false;
  215.93 -            for (int i = 0;; i++) {
  215.94 -                String p = request.getParameter("param" + i);
  215.95 -                if (p == null) {
  215.96 -                    break;
  215.97 -                }
  215.98 -                if ("protocol:ws".equals(p)) {
  215.99 -                    webSocket = true;
 215.100 -                    continue;
 215.101 -                }
 215.102 -                params.add(p);
 215.103 -            }
 215.104 -            final String cnt = request.getParameter("content");
 215.105 -            String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
 215.106 -            ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
 215.107 -            URI url;
 215.108 -            final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
 215.109 -            if (webSocket) {
 215.110 -                url = registerWebSocket(res);
 215.111 -            } else {
 215.112 -                url = registerResource(res);
 215.113 -            }
 215.114 -            response.getWriter().write(url.toString());
 215.115 -            response.getWriter().write("\n");
 215.116 -            return;
 215.117 -        }
 215.118 -
 215.119 -        for (Resource r : resources) {
 215.120 -            if (r.httpPath.equals(request.getRequestURI())) {
 215.121 -                response.setContentType(r.httpType);
 215.122 -                r.httpContent.reset();
 215.123 -                String[] params = null;
 215.124 -                if (r.parameters.length != 0) {
 215.125 -                    params = new String[r.parameters.length];
 215.126 -                    for (int i = 0; i < r.parameters.length; i++) {
 215.127 -                        params[i] = request.getParameter(r.parameters[i]);
 215.128 -                        if (params[i] == null) {
 215.129 -                            if ("http.method".equals(r.parameters[i])) {
 215.130 -                                params[i] = request.getMethod().toString();
 215.131 -                            } else if ("http.requestBody".equals(r.parameters[i])) {
 215.132 -                                Reader rdr = request.getReader();
 215.133 -                                StringBuilder sb = new StringBuilder();
 215.134 -                                for (;;) {
 215.135 -                                    int ch = rdr.read();
 215.136 -                                    if (ch == -1) {
 215.137 -                                        break;
 215.138 -                                    }
 215.139 -                                    sb.append((char) ch);
 215.140 -                                }
 215.141 -                                params[i] = sb.toString();
 215.142 -                            }
 215.143 -                        }
 215.144 -                        if (params[i] == null) {
 215.145 -                            params[i] = "null";
 215.146 -                        }
 215.147 -                    }
 215.148 -                }
 215.149 -
 215.150 -                copyStream(r.httpContent, response.getOutputStream(), null, params);
 215.151 -            }
 215.152 -        }
 215.153 -    }
 215.154 -    
 215.155 -    private URI registerWebSocket(Resource r) {
 215.156 -        WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
 215.157 -        return pageURL("ws", server, r.httpPath);
 215.158 -    }
 215.159 -
 215.160 -    private URI registerResource(Resource r) {
 215.161 -        if (!resources.contains(r)) {
 215.162 -            resources.add(r);
 215.163 -            conf.addHttpHandler(this, r.httpPath);
 215.164 -        }
 215.165 -        return pageURL("http", server, r.httpPath);
 215.166 -    }
 215.167 -    
 215.168 -    private static URI pageURL(String proto, HttpServer server, final String page) {
 215.169 -        NetworkListener listener = server.getListeners().iterator().next();
 215.170 -        int port = listener.getPort();
 215.171 -        try {
 215.172 -            return new URI(proto + "://localhost:" + port + page);
 215.173 -        } catch (URISyntaxException ex) {
 215.174 -            throw new IllegalStateException(ex);
 215.175 -        }
 215.176 -    }
 215.177 -    
 215.178 -    static final class Resource {
 215.179 -
 215.180 -        final InputStream httpContent;
 215.181 -        final String httpType;
 215.182 -        final String httpPath;
 215.183 -        final String[] parameters;
 215.184 -
 215.185 -        Resource(InputStream httpContent, String httpType, String httpPath,
 215.186 -            String[] parameters) {
 215.187 -            httpContent.mark(Integer.MAX_VALUE);
 215.188 -            this.httpContent = httpContent;
 215.189 -            this.httpType = httpType;
 215.190 -            this.httpPath = httpPath;
 215.191 -            this.parameters = parameters;
 215.192 -        }
 215.193 -    }
 215.194 -
 215.195 -    static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
 215.196 -        for (;;) {
 215.197 -            int ch = is.read();
 215.198 -            if (ch == -1) {
 215.199 -                break;
 215.200 -            }
 215.201 -            if (ch == '$' && params.length > 0) {
 215.202 -                int cnt = is.read() - '0';
 215.203 -                if (baseURL != null && cnt == 'U' - '0') {
 215.204 -                    os.write(baseURL.getBytes("UTF-8"));
 215.205 -                } else {
 215.206 -                    if (cnt >= 0 && cnt < params.length) {
 215.207 -                        os.write(params[cnt].getBytes("UTF-8"));
 215.208 -                    } else {
 215.209 -                        os.write('$');
 215.210 -                        os.write(cnt + '0');
 215.211 -                    }
 215.212 -                }
 215.213 -            } else {
 215.214 -                os.write(ch);
 215.215 -            }
 215.216 -        }
 215.217 -    }
 215.218 -    
 215.219 -    private static class WS extends WebSocketApplication {
 215.220 -        private final Resource r;
 215.221 -
 215.222 -        private WS(Resource r) {
 215.223 -            this.r = r;
 215.224 -        }
 215.225 -
 215.226 -        @Override
 215.227 -        public void onMessage(WebSocket socket, String text) {
 215.228 -            try {
 215.229 -                r.httpContent.reset();
 215.230 -                ByteArrayOutputStream out = new ByteArrayOutputStream();
 215.231 -                copyStream(r.httpContent, out, null, text);
 215.232 -                String s = new String(out.toByteArray(), "UTF-8");
 215.233 -                socket.send(s);
 215.234 -            } catch (IOException ex) {
 215.235 -                LOG.log(Level.WARNING, null, ex);
 215.236 -            }
 215.237 -        }
 215.238 -        private static final Logger LOG = Logger.getLogger(WS.class.getName());
 215.239 -        
 215.240 -    }
 215.241 -}
   216.1 --- a/ko-ws-tyrus/src/test/java/org/apidesign/html/wstyrus/TyrusFX.java	Thu Dec 19 17:11:01 2013 +0100
   216.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   216.3 @@ -1,98 +0,0 @@
   216.4 -/**
   216.5 - * HTML via Java(tm) Language Bindings
   216.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   216.7 - *
   216.8 - * This program is free software: you can redistribute it and/or modify
   216.9 - * it under the terms of the GNU General Public License as published by
  216.10 - * the Free Software Foundation, version 2 of the License.
  216.11 - *
  216.12 - * This program is distributed in the hope that it will be useful,
  216.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  216.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  216.15 - * GNU General Public License for more details. apidesign.org
  216.16 - * designates this particular file as subject to the
  216.17 - * "Classpath" exception as provided by apidesign.org
  216.18 - * in the License file that accompanied this code.
  216.19 - *
  216.20 - * You should have received a copy of the GNU General Public License
  216.21 - * along with this program. Look for COPYING file in the top folder.
  216.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  216.23 - */
  216.24 -package org.apidesign.html.wstyrus;
  216.25 -
  216.26 -import java.lang.reflect.InvocationTargetException;
  216.27 -import java.lang.reflect.Method;
  216.28 -import javafx.application.Platform;
  216.29 -import org.apidesign.html.boot.impl.FnContext;
  216.30 -import org.apidesign.html.boot.spi.Fn;
  216.31 -import org.testng.ITest;
  216.32 -import org.testng.annotations.Test;
  216.33 -
  216.34 -/**
  216.35 - *
  216.36 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  216.37 - */
  216.38 -public final class TyrusFX implements ITest, Runnable {
  216.39 -    private final Fn.Presenter p;
  216.40 -    private final Method m;
  216.41 -    private Object result;
  216.42 -    private Object inst;
  216.43 -    private int count;
  216.44 -
  216.45 -    TyrusFX(Fn.Presenter p, Method m) {
  216.46 -        this.p = p;
  216.47 -        this.m = m;
  216.48 -    }
  216.49 -
  216.50 -    @Override
  216.51 -    public String getTestName() {
  216.52 -        return m.getName();
  216.53 -    }
  216.54 -
  216.55 -    @Test
  216.56 -    public synchronized void executeTest() throws Exception {
  216.57 -        if (result == null) {
  216.58 -            Platform.runLater(this);
  216.59 -            wait();
  216.60 -        }
  216.61 -        if (result instanceof Exception) {
  216.62 -            throw (Exception)result;
  216.63 -        }
  216.64 -        if (result instanceof Error) {
  216.65 -            throw (Error)result;
  216.66 -        }
  216.67 -    }
  216.68 -
  216.69 -    @Override
  216.70 -    public synchronized void run() {
  216.71 -        boolean notify = true;
  216.72 -        try {
  216.73 -            FnContext.currentPresenter(p);
  216.74 -            if (inst == null) {
  216.75 -                inst = m.getDeclaringClass().newInstance();
  216.76 -            }
  216.77 -            result = m.invoke(inst);
  216.78 -            if (result == null) {
  216.79 -                result = this;
  216.80 -            }
  216.81 -        } catch (InvocationTargetException ex) {
  216.82 -            Throwable r = ex.getTargetException();
  216.83 -            if (r instanceof InterruptedException) {
  216.84 -                if (count++ < 10000) {
  216.85 -                    notify = false;
  216.86 -                    Platform.runLater(this);
  216.87 -                    return;
  216.88 -                }
  216.89 -            }
  216.90 -            result = r;
  216.91 -        } catch (Exception ex) {
  216.92 -            result = ex;
  216.93 -        } finally {
  216.94 -            if (notify) {
  216.95 -                notifyAll();
  216.96 -            }
  216.97 -            FnContext.currentPresenter(null);
  216.98 -        }
  216.99 -    }
 216.100 -    
 216.101 -}
   217.1 --- a/ko-ws-tyrus/src/test/java/org/apidesign/html/wstyrus/TyrusKnockoutTest.java	Thu Dec 19 17:11:01 2013 +0100
   217.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   217.3 @@ -1,191 +0,0 @@
   217.4 -/**
   217.5 - * HTML via Java(tm) Language Bindings
   217.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   217.7 - *
   217.8 - * This program is free software: you can redistribute it and/or modify
   217.9 - * it under the terms of the GNU General Public License as published by
  217.10 - * the Free Software Foundation, version 2 of the License.
  217.11 - *
  217.12 - * This program is distributed in the hope that it will be useful,
  217.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  217.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  217.15 - * GNU General Public License for more details. apidesign.org
  217.16 - * designates this particular file as subject to the
  217.17 - * "Classpath" exception as provided by apidesign.org
  217.18 - * in the License file that accompanied this code.
  217.19 - *
  217.20 - * You should have received a copy of the GNU General Public License
  217.21 - * along with this program. Look for COPYING file in the top folder.
  217.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  217.23 - */
  217.24 -package org.apidesign.html.wstyrus;
  217.25 -
  217.26 -import java.io.BufferedReader;
  217.27 -import java.io.IOException;
  217.28 -import java.io.InputStreamReader;
  217.29 -import java.lang.annotation.Annotation;
  217.30 -import java.lang.reflect.Method;
  217.31 -import java.net.URI;
  217.32 -import java.net.URISyntaxException;
  217.33 -import java.net.URL;
  217.34 -import java.net.URLConnection;
  217.35 -import java.util.ArrayList;
  217.36 -import java.util.List;
  217.37 -import java.util.Map;
  217.38 -import java.util.concurrent.Executors;
  217.39 -import net.java.html.BrwsrCtx;
  217.40 -import net.java.html.boot.BrowserBuilder;
  217.41 -import net.java.html.js.JavaScriptBody;
  217.42 -import org.apidesign.html.boot.impl.FnContext;
  217.43 -import org.apidesign.html.boot.impl.FnUtils;
  217.44 -import org.apidesign.html.boot.spi.Fn;
  217.45 -import org.apidesign.html.context.spi.Contexts;
  217.46 -import org.apidesign.html.json.spi.Technology;
  217.47 -import org.apidesign.html.json.spi.Transfer;
  217.48 -import org.apidesign.html.json.spi.WSTransfer;
  217.49 -import org.apidesign.html.json.tck.KOTest;
  217.50 -import org.apidesign.html.json.tck.KnockoutTCK;
  217.51 -import org.apidesign.html.kofx.FXContext;
  217.52 -import org.json.JSONException;
  217.53 -import org.json.JSONObject;
  217.54 -import org.openide.util.lookup.ServiceProvider;
  217.55 -import org.testng.annotations.Factory;
  217.56 -import static org.testng.Assert.*;
  217.57 -
  217.58 -/**
  217.59 - *
  217.60 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  217.61 - */
  217.62 -@ServiceProvider(service = KnockoutTCK.class)
  217.63 -public final class TyrusKnockoutTest extends KnockoutTCK {
  217.64 -    private static Class<?> browserClass;
  217.65 -    private static Fn.Presenter browserContext;
  217.66 -    
  217.67 -    public TyrusKnockoutTest() {
  217.68 -    }
  217.69 -    
  217.70 -    @Factory public static Object[] compatibilityTests() throws Exception {
  217.71 -        Class[] arr = testClasses();
  217.72 -        for (int i = 0; i < arr.length; i++) {
  217.73 -            assertEquals(
  217.74 -                arr[i].getClassLoader(),
  217.75 -                TyrusKnockoutTest.class.getClassLoader(),
  217.76 -                "All classes loaded by the same classloader"
  217.77 -            );
  217.78 -        }
  217.79 -        
  217.80 -        URI uri = TyrusDynamicHTTP.initServer();
  217.81 -    
  217.82 -        final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(TyrusKnockoutTest.class).
  217.83 -            loadPage(uri.toString()).
  217.84 -            invoke("initialized");
  217.85 -        
  217.86 -        Executors.newSingleThreadExecutor().submit(new Runnable() {
  217.87 -            @Override
  217.88 -            public void run() {
  217.89 -                bb.showAndWait();
  217.90 -            }
  217.91 -        });
  217.92 -        
  217.93 -        ClassLoader l = getClassLoader();
  217.94 -        List<Object> res = new ArrayList<Object>();
  217.95 -        for (int i = 0; i < arr.length; i++) {
  217.96 -            Class<?> c = Class.forName(arr[i].getName(), true, l);
  217.97 -            Class<? extends Annotation> koTest = 
  217.98 -                c.getClassLoader().loadClass(KOTest.class.getName()).
  217.99 -                asSubclass(Annotation.class);
 217.100 -            for (Method m : c.getMethods()) {
 217.101 -                if (m.getAnnotation(koTest) != null) {
 217.102 -                    res.add(new TyrusFX(browserContext, m));
 217.103 -                }
 217.104 -            }
 217.105 -        }
 217.106 -        return res.toArray();
 217.107 -    }
 217.108 -
 217.109 -    static synchronized ClassLoader getClassLoader() throws InterruptedException {
 217.110 -        while (browserClass == null) {
 217.111 -            TyrusKnockoutTest.class.wait();
 217.112 -        }
 217.113 -        return browserClass.getClassLoader();
 217.114 -    }
 217.115 -    
 217.116 -    public static synchronized void initialized(Class<?> browserCls) throws Exception {
 217.117 -        browserClass = browserCls;
 217.118 -        browserContext = Fn.activePresenter();
 217.119 -        TyrusKnockoutTest.class.notifyAll();
 217.120 -    }
 217.121 -    
 217.122 -    public static void initialized() throws Exception {
 217.123 -        Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(TyrusKnockoutTest.class.getName());
 217.124 -        Method m = classpathClass.getMethod("initialized", Class.class);
 217.125 -        m.invoke(null, TyrusKnockoutTest.class);
 217.126 -        browserContext = Fn.activePresenter();
 217.127 -    }
 217.128 -    
 217.129 -    @Override
 217.130 -    public BrwsrCtx createContext() {
 217.131 -        FXContext fx = new FXContext(browserContext);
 217.132 -        TyrusContext tc = new TyrusContext();
 217.133 -        Contexts.Builder cb = Contexts.newBuilder().
 217.134 -            register(Technology.class, fx, 10).
 217.135 -            register(Transfer.class, fx, 10).
 217.136 -            register(WSTransfer.class, tc, 10);
 217.137 -        return cb.build();
 217.138 -    }
 217.139 -
 217.140 -    @Override
 217.141 -    public Object createJSON(Map<String, Object> values) {
 217.142 -        JSONObject json = new JSONObject();
 217.143 -        for (Map.Entry<String, Object> entry : values.entrySet()) {
 217.144 -            try {
 217.145 -                json.put(entry.getKey(), entry.getValue());
 217.146 -            } catch (JSONException ex) {
 217.147 -                throw new IllegalStateException(ex);
 217.148 -            }
 217.149 -        }
 217.150 -        return json;
 217.151 -    }
 217.152 -
 217.153 -    @Override
 217.154 -    @JavaScriptBody(args = { "s", "args" }, body = ""
 217.155 -        + "var f = new Function(s); "
 217.156 -        + "return f.apply(null, args);"
 217.157 -    )
 217.158 -    public native Object executeScript(String script, Object[] arguments);
 217.159 -
 217.160 -    @JavaScriptBody(args = {  }, body = 
 217.161 -          "var h;"
 217.162 -        + "if (!!window && !!window.location && !!window.location.href)\n"
 217.163 -        + "  h = window.location.href;\n"
 217.164 -        + "else "
 217.165 -        + "  h = null;"
 217.166 -        + "return h;\n"
 217.167 -    )
 217.168 -    private static native String findBaseURL();
 217.169 -    
 217.170 -    @Override
 217.171 -    public URI prepareURL(String content, String mimeType, String[] parameters) {
 217.172 -        try {
 217.173 -            final URL baseURL = new URL(findBaseURL());
 217.174 -            StringBuilder sb = new StringBuilder();
 217.175 -            sb.append("/dynamic?mimeType=").append(mimeType);
 217.176 -            for (int i = 0; i < parameters.length; i++) {
 217.177 -                sb.append("&param" + i).append("=").append(parameters[i]);
 217.178 -            }
 217.179 -            String mangle = content.replace("\n", "%0a")
 217.180 -                .replace("\"", "\\\"").replace(" ", "%20");
 217.181 -            sb.append("&content=").append(mangle);
 217.182 -
 217.183 -            URL query = new URL(baseURL, sb.toString());
 217.184 -            URLConnection c = query.openConnection();
 217.185 -            BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
 217.186 -            URI connectTo = new URI(br.readLine());
 217.187 -            return connectTo;
 217.188 -        } catch (IOException ex) {
 217.189 -            throw new IllegalStateException(ex);
 217.190 -        } catch (URISyntaxException ex) {
 217.191 -            throw new IllegalStateException(ex);
 217.192 -        }
 217.193 -    }
 217.194 -}
   218.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   218.2 +++ b/ko-ws-tyrus/src/test/java/org/netbeans/html/wstyrus/TyrusDynamicHTTP.java	Tue Jan 07 08:21:57 2014 +0100
   218.3 @@ -0,0 +1,260 @@
   218.4 +/**
   218.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   218.6 + *
   218.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   218.8 + *
   218.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  218.10 + * Other names may be trademarks of their respective owners.
  218.11 + *
  218.12 + * The contents of this file are subject to the terms of either the GNU
  218.13 + * General Public License Version 2 only ("GPL") or the Common
  218.14 + * Development and Distribution License("CDDL") (collectively, the
  218.15 + * "License"). You may not use this file except in compliance with the
  218.16 + * License. You can obtain a copy of the License at
  218.17 + * http://www.netbeans.org/cddl-gplv2.html
  218.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  218.19 + * specific language governing permissions and limitations under the
  218.20 + * License.  When distributing the software, include this License Header
  218.21 + * Notice in each file and include the License file at
  218.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  218.23 + * particular file as subject to the "Classpath" exception as provided
  218.24 + * by Oracle in the GPL Version 2 section of the License file that
  218.25 + * accompanied this code. If applicable, add the following below the
  218.26 + * License Header, with the fields enclosed by brackets [] replaced by
  218.27 + * your own identifying information:
  218.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  218.29 + *
  218.30 + * Contributor(s):
  218.31 + *
  218.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  218.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  218.34 + *
  218.35 + * If you wish your version of this file to be governed by only the CDDL
  218.36 + * or only the GPL Version 2, indicate your decision by adding
  218.37 + * "[Contributor] elects to include this software in this distribution
  218.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  218.39 + * single choice of license, a recipient has the option to distribute
  218.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  218.41 + * to extend the choice of license to its licensees as provided above.
  218.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  218.43 + * Version 2 license, then the option applies only if the new code is
  218.44 + * made subject to such option by the copyright holder.
  218.45 + */
  218.46 +package org.netbeans.html.wstyrus;
  218.47 +
  218.48 +import java.io.ByteArrayInputStream;
  218.49 +import java.io.ByteArrayOutputStream;
  218.50 +import java.io.IOException;
  218.51 +import java.io.InputStream;
  218.52 +import java.io.OutputStream;
  218.53 +import java.io.Reader;
  218.54 +import java.net.URI;
  218.55 +import java.net.URISyntaxException;
  218.56 +import java.util.ArrayList;
  218.57 +import java.util.List;
  218.58 +import java.util.logging.Level;
  218.59 +import java.util.logging.Logger;
  218.60 +import org.glassfish.grizzly.PortRange;
  218.61 +import org.glassfish.grizzly.http.server.HttpHandler;
  218.62 +import org.glassfish.grizzly.http.server.HttpServer;
  218.63 +import org.glassfish.grizzly.http.server.NetworkListener;
  218.64 +import org.glassfish.grizzly.http.server.Request;
  218.65 +import org.glassfish.grizzly.http.server.Response;
  218.66 +import org.glassfish.grizzly.http.server.ServerConfiguration;
  218.67 +import org.glassfish.grizzly.websockets.WebSocket;
  218.68 +import org.glassfish.grizzly.websockets.WebSocketAddOn;
  218.69 +import org.glassfish.grizzly.websockets.WebSocketApplication;
  218.70 +import org.glassfish.grizzly.websockets.WebSocketEngine;
  218.71 +
  218.72 +/**
  218.73 + *
  218.74 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  218.75 + */
  218.76 +final class TyrusDynamicHTTP extends HttpHandler {
  218.77 +    private static int resourcesCount;
  218.78 +    private static List<Resource> resources;
  218.79 +    private static ServerConfiguration conf;
  218.80 +    private static HttpServer server;
  218.81 +    
  218.82 +    private TyrusDynamicHTTP() {
  218.83 +    }
  218.84 +    
  218.85 +    static URI initServer() throws Exception {
  218.86 +        server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
  218.87 +        final WebSocketAddOn addon = new WebSocketAddOn();
  218.88 +        for (NetworkListener listener : server.getListeners()) {
  218.89 +            listener.registerAddOn(addon);
  218.90 +        }        
  218.91 +        resources = new ArrayList<Resource>();
  218.92 +
  218.93 +        conf = server.getServerConfiguration();
  218.94 +        final TyrusDynamicHTTP dh = new TyrusDynamicHTTP();
  218.95 +
  218.96 +        conf.addHttpHandler(dh, "/");
  218.97 +        
  218.98 +        server.start();
  218.99 +
 218.100 +        return pageURL("http", server, "/test.html");
 218.101 +    }
 218.102 +    
 218.103 +    @Override
 218.104 +    public void service(Request request, Response response) throws Exception {
 218.105 +        if ("/test.html".equals(request.getRequestURI())) {
 218.106 +            response.setContentType("text/html");
 218.107 +            final InputStream is = TyrusDynamicHTTP.class.getResourceAsStream("test.html");
 218.108 +            copyStream(is, response.getOutputStream(), null);
 218.109 +            return;
 218.110 +        }
 218.111 +        if ("/dynamic".equals(request.getRequestURI())) {
 218.112 +            String mimeType = request.getParameter("mimeType");
 218.113 +            List<String> params = new ArrayList<String>();
 218.114 +            boolean webSocket = false;
 218.115 +            for (int i = 0;; i++) {
 218.116 +                String p = request.getParameter("param" + i);
 218.117 +                if (p == null) {
 218.118 +                    break;
 218.119 +                }
 218.120 +                if ("protocol:ws".equals(p)) {
 218.121 +                    webSocket = true;
 218.122 +                    continue;
 218.123 +                }
 218.124 +                params.add(p);
 218.125 +            }
 218.126 +            final String cnt = request.getParameter("content");
 218.127 +            String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
 218.128 +            ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
 218.129 +            URI url;
 218.130 +            final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
 218.131 +            if (webSocket) {
 218.132 +                url = registerWebSocket(res);
 218.133 +            } else {
 218.134 +                url = registerResource(res);
 218.135 +            }
 218.136 +            response.getWriter().write(url.toString());
 218.137 +            response.getWriter().write("\n");
 218.138 +            return;
 218.139 +        }
 218.140 +
 218.141 +        for (Resource r : resources) {
 218.142 +            if (r.httpPath.equals(request.getRequestURI())) {
 218.143 +                response.setContentType(r.httpType);
 218.144 +                r.httpContent.reset();
 218.145 +                String[] params = null;
 218.146 +                if (r.parameters.length != 0) {
 218.147 +                    params = new String[r.parameters.length];
 218.148 +                    for (int i = 0; i < r.parameters.length; i++) {
 218.149 +                        params[i] = request.getParameter(r.parameters[i]);
 218.150 +                        if (params[i] == null) {
 218.151 +                            if ("http.method".equals(r.parameters[i])) {
 218.152 +                                params[i] = request.getMethod().toString();
 218.153 +                            } else if ("http.requestBody".equals(r.parameters[i])) {
 218.154 +                                Reader rdr = request.getReader();
 218.155 +                                StringBuilder sb = new StringBuilder();
 218.156 +                                for (;;) {
 218.157 +                                    int ch = rdr.read();
 218.158 +                                    if (ch == -1) {
 218.159 +                                        break;
 218.160 +                                    }
 218.161 +                                    sb.append((char) ch);
 218.162 +                                }
 218.163 +                                params[i] = sb.toString();
 218.164 +                            }
 218.165 +                        }
 218.166 +                        if (params[i] == null) {
 218.167 +                            params[i] = "null";
 218.168 +                        }
 218.169 +                    }
 218.170 +                }
 218.171 +
 218.172 +                copyStream(r.httpContent, response.getOutputStream(), null, params);
 218.173 +            }
 218.174 +        }
 218.175 +    }
 218.176 +    
 218.177 +    private URI registerWebSocket(Resource r) {
 218.178 +        WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
 218.179 +        return pageURL("ws", server, r.httpPath);
 218.180 +    }
 218.181 +
 218.182 +    private URI registerResource(Resource r) {
 218.183 +        if (!resources.contains(r)) {
 218.184 +            resources.add(r);
 218.185 +            conf.addHttpHandler(this, r.httpPath);
 218.186 +        }
 218.187 +        return pageURL("http", server, r.httpPath);
 218.188 +    }
 218.189 +    
 218.190 +    private static URI pageURL(String proto, HttpServer server, final String page) {
 218.191 +        NetworkListener listener = server.getListeners().iterator().next();
 218.192 +        int port = listener.getPort();
 218.193 +        try {
 218.194 +            return new URI(proto + "://localhost:" + port + page);
 218.195 +        } catch (URISyntaxException ex) {
 218.196 +            throw new IllegalStateException(ex);
 218.197 +        }
 218.198 +    }
 218.199 +    
 218.200 +    static final class Resource {
 218.201 +
 218.202 +        final InputStream httpContent;
 218.203 +        final String httpType;
 218.204 +        final String httpPath;
 218.205 +        final String[] parameters;
 218.206 +
 218.207 +        Resource(InputStream httpContent, String httpType, String httpPath,
 218.208 +            String[] parameters) {
 218.209 +            httpContent.mark(Integer.MAX_VALUE);
 218.210 +            this.httpContent = httpContent;
 218.211 +            this.httpType = httpType;
 218.212 +            this.httpPath = httpPath;
 218.213 +            this.parameters = parameters;
 218.214 +        }
 218.215 +    }
 218.216 +
 218.217 +    static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
 218.218 +        for (;;) {
 218.219 +            int ch = is.read();
 218.220 +            if (ch == -1) {
 218.221 +                break;
 218.222 +            }
 218.223 +            if (ch == '$' && params.length > 0) {
 218.224 +                int cnt = is.read() - '0';
 218.225 +                if (baseURL != null && cnt == 'U' - '0') {
 218.226 +                    os.write(baseURL.getBytes("UTF-8"));
 218.227 +                } else {
 218.228 +                    if (cnt >= 0 && cnt < params.length) {
 218.229 +                        os.write(params[cnt].getBytes("UTF-8"));
 218.230 +                    } else {
 218.231 +                        os.write('$');
 218.232 +                        os.write(cnt + '0');
 218.233 +                    }
 218.234 +                }
 218.235 +            } else {
 218.236 +                os.write(ch);
 218.237 +            }
 218.238 +        }
 218.239 +    }
 218.240 +    
 218.241 +    private static class WS extends WebSocketApplication {
 218.242 +        private final Resource r;
 218.243 +
 218.244 +        private WS(Resource r) {
 218.245 +            this.r = r;
 218.246 +        }
 218.247 +
 218.248 +        @Override
 218.249 +        public void onMessage(WebSocket socket, String text) {
 218.250 +            try {
 218.251 +                r.httpContent.reset();
 218.252 +                ByteArrayOutputStream out = new ByteArrayOutputStream();
 218.253 +                copyStream(r.httpContent, out, null, text);
 218.254 +                String s = new String(out.toByteArray(), "UTF-8");
 218.255 +                socket.send(s);
 218.256 +            } catch (IOException ex) {
 218.257 +                LOG.log(Level.WARNING, null, ex);
 218.258 +            }
 218.259 +        }
 218.260 +        private static final Logger LOG = Logger.getLogger(WS.class.getName());
 218.261 +        
 218.262 +    }
 218.263 +}
   219.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   219.2 +++ b/ko-ws-tyrus/src/test/java/org/netbeans/html/wstyrus/TyrusFX.java	Tue Jan 07 08:21:57 2014 +0100
   219.3 @@ -0,0 +1,120 @@
   219.4 +/**
   219.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   219.6 + *
   219.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   219.8 + *
   219.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  219.10 + * Other names may be trademarks of their respective owners.
  219.11 + *
  219.12 + * The contents of this file are subject to the terms of either the GNU
  219.13 + * General Public License Version 2 only ("GPL") or the Common
  219.14 + * Development and Distribution License("CDDL") (collectively, the
  219.15 + * "License"). You may not use this file except in compliance with the
  219.16 + * License. You can obtain a copy of the License at
  219.17 + * http://www.netbeans.org/cddl-gplv2.html
  219.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  219.19 + * specific language governing permissions and limitations under the
  219.20 + * License.  When distributing the software, include this License Header
  219.21 + * Notice in each file and include the License file at
  219.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  219.23 + * particular file as subject to the "Classpath" exception as provided
  219.24 + * by Oracle in the GPL Version 2 section of the License file that
  219.25 + * accompanied this code. If applicable, add the following below the
  219.26 + * License Header, with the fields enclosed by brackets [] replaced by
  219.27 + * your own identifying information:
  219.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  219.29 + *
  219.30 + * Contributor(s):
  219.31 + *
  219.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  219.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  219.34 + *
  219.35 + * If you wish your version of this file to be governed by only the CDDL
  219.36 + * or only the GPL Version 2, indicate your decision by adding
  219.37 + * "[Contributor] elects to include this software in this distribution
  219.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  219.39 + * single choice of license, a recipient has the option to distribute
  219.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  219.41 + * to extend the choice of license to its licensees as provided above.
  219.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  219.43 + * Version 2 license, then the option applies only if the new code is
  219.44 + * made subject to such option by the copyright holder.
  219.45 + */
  219.46 +package org.netbeans.html.wstyrus;
  219.47 +
  219.48 +import java.lang.reflect.InvocationTargetException;
  219.49 +import java.lang.reflect.Method;
  219.50 +import javafx.application.Platform;
  219.51 +import org.netbeans.html.boot.impl.FnContext;
  219.52 +import org.apidesign.html.boot.spi.Fn;
  219.53 +import org.testng.ITest;
  219.54 +import org.testng.annotations.Test;
  219.55 +
  219.56 +/**
  219.57 + *
  219.58 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  219.59 + */
  219.60 +public final class TyrusFX implements ITest, Runnable {
  219.61 +    private final Fn.Presenter p;
  219.62 +    private final Method m;
  219.63 +    private Object result;
  219.64 +    private Object inst;
  219.65 +    private int count;
  219.66 +
  219.67 +    TyrusFX(Fn.Presenter p, Method m) {
  219.68 +        this.p = p;
  219.69 +        this.m = m;
  219.70 +    }
  219.71 +
  219.72 +    @Override
  219.73 +    public String getTestName() {
  219.74 +        return m.getName();
  219.75 +    }
  219.76 +
  219.77 +    @Test
  219.78 +    public synchronized void executeTest() throws Exception {
  219.79 +        if (result == null) {
  219.80 +            Platform.runLater(this);
  219.81 +            wait();
  219.82 +        }
  219.83 +        if (result instanceof Exception) {
  219.84 +            throw (Exception)result;
  219.85 +        }
  219.86 +        if (result instanceof Error) {
  219.87 +            throw (Error)result;
  219.88 +        }
  219.89 +    }
  219.90 +
  219.91 +    @Override
  219.92 +    public synchronized void run() {
  219.93 +        boolean notify = true;
  219.94 +        try {
  219.95 +            FnContext.currentPresenter(p);
  219.96 +            if (inst == null) {
  219.97 +                inst = m.getDeclaringClass().newInstance();
  219.98 +            }
  219.99 +            result = m.invoke(inst);
 219.100 +            if (result == null) {
 219.101 +                result = this;
 219.102 +            }
 219.103 +        } catch (InvocationTargetException ex) {
 219.104 +            Throwable r = ex.getTargetException();
 219.105 +            if (r instanceof InterruptedException) {
 219.106 +                if (count++ < 10000) {
 219.107 +                    notify = false;
 219.108 +                    Platform.runLater(this);
 219.109 +                    return;
 219.110 +                }
 219.111 +            }
 219.112 +            result = r;
 219.113 +        } catch (Exception ex) {
 219.114 +            result = ex;
 219.115 +        } finally {
 219.116 +            if (notify) {
 219.117 +                notifyAll();
 219.118 +            }
 219.119 +            FnContext.currentPresenter(null);
 219.120 +        }
 219.121 +    }
 219.122 +    
 219.123 +}
   220.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   220.2 +++ b/ko-ws-tyrus/src/test/java/org/netbeans/html/wstyrus/TyrusKnockoutTest.java	Tue Jan 07 08:21:57 2014 +0100
   220.3 @@ -0,0 +1,212 @@
   220.4 +/**
   220.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   220.6 + *
   220.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   220.8 + *
   220.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  220.10 + * Other names may be trademarks of their respective owners.
  220.11 + *
  220.12 + * The contents of this file are subject to the terms of either the GNU
  220.13 + * General Public License Version 2 only ("GPL") or the Common
  220.14 + * Development and Distribution License("CDDL") (collectively, the
  220.15 + * "License"). You may not use this file except in compliance with the
  220.16 + * License. You can obtain a copy of the License at
  220.17 + * http://www.netbeans.org/cddl-gplv2.html
  220.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  220.19 + * specific language governing permissions and limitations under the
  220.20 + * License.  When distributing the software, include this License Header
  220.21 + * Notice in each file and include the License file at
  220.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  220.23 + * particular file as subject to the "Classpath" exception as provided
  220.24 + * by Oracle in the GPL Version 2 section of the License file that
  220.25 + * accompanied this code. If applicable, add the following below the
  220.26 + * License Header, with the fields enclosed by brackets [] replaced by
  220.27 + * your own identifying information:
  220.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  220.29 + *
  220.30 + * Contributor(s):
  220.31 + *
  220.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  220.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  220.34 + *
  220.35 + * If you wish your version of this file to be governed by only the CDDL
  220.36 + * or only the GPL Version 2, indicate your decision by adding
  220.37 + * "[Contributor] elects to include this software in this distribution
  220.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  220.39 + * single choice of license, a recipient has the option to distribute
  220.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  220.41 + * to extend the choice of license to its licensees as provided above.
  220.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  220.43 + * Version 2 license, then the option applies only if the new code is
  220.44 + * made subject to such option by the copyright holder.
  220.45 + */
  220.46 +package org.netbeans.html.wstyrus;
  220.47 +
  220.48 +import java.io.BufferedReader;
  220.49 +import java.io.IOException;
  220.50 +import java.io.InputStreamReader;
  220.51 +import java.lang.annotation.Annotation;
  220.52 +import java.lang.reflect.Method;
  220.53 +import java.net.URI;
  220.54 +import java.net.URISyntaxException;
  220.55 +import java.net.URL;
  220.56 +import java.net.URLConnection;
  220.57 +import java.util.ArrayList;
  220.58 +import java.util.List;
  220.59 +import java.util.Map;
  220.60 +import java.util.concurrent.Executors;
  220.61 +import net.java.html.BrwsrCtx;
  220.62 +import net.java.html.boot.BrowserBuilder;
  220.63 +import net.java.html.js.JavaScriptBody;
  220.64 +import org.netbeans.html.boot.impl.FnContext;
  220.65 +import org.apidesign.html.boot.spi.Fn;
  220.66 +import org.apidesign.html.context.spi.Contexts;
  220.67 +import org.apidesign.html.json.spi.Technology;
  220.68 +import org.apidesign.html.json.spi.Transfer;
  220.69 +import org.apidesign.html.json.spi.WSTransfer;
  220.70 +import org.apidesign.html.json.tck.KOTest;
  220.71 +import org.apidesign.html.json.tck.KnockoutTCK;
  220.72 +import org.json.JSONException;
  220.73 +import org.json.JSONObject;
  220.74 +import org.netbeans.html.kofx.FXContext;
  220.75 +import org.openide.util.lookup.ServiceProvider;
  220.76 +import org.testng.annotations.Factory;
  220.77 +import static org.testng.Assert.*;
  220.78 +
  220.79 +/**
  220.80 + *
  220.81 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  220.82 + */
  220.83 +@ServiceProvider(service = KnockoutTCK.class)
  220.84 +public final class TyrusKnockoutTest extends KnockoutTCK {
  220.85 +    private static Class<?> browserClass;
  220.86 +    private static Fn.Presenter browserContext;
  220.87 +    
  220.88 +    public TyrusKnockoutTest() {
  220.89 +    }
  220.90 +    
  220.91 +    @Factory public static Object[] compatibilityTests() throws Exception {
  220.92 +        Class[] arr = testClasses();
  220.93 +        for (int i = 0; i < arr.length; i++) {
  220.94 +            assertEquals(
  220.95 +                arr[i].getClassLoader(),
  220.96 +                TyrusKnockoutTest.class.getClassLoader(),
  220.97 +                "All classes loaded by the same classloader"
  220.98 +            );
  220.99 +        }
 220.100 +        
 220.101 +        URI uri = TyrusDynamicHTTP.initServer();
 220.102 +    
 220.103 +        final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(TyrusKnockoutTest.class).
 220.104 +            loadPage(uri.toString()).
 220.105 +            invoke("initialized");
 220.106 +        
 220.107 +        Executors.newSingleThreadExecutor().submit(new Runnable() {
 220.108 +            @Override
 220.109 +            public void run() {
 220.110 +                bb.showAndWait();
 220.111 +            }
 220.112 +        });
 220.113 +        
 220.114 +        ClassLoader l = getClassLoader();
 220.115 +        List<Object> res = new ArrayList<Object>();
 220.116 +        for (int i = 0; i < arr.length; i++) {
 220.117 +            Class<?> c = Class.forName(arr[i].getName(), true, l);
 220.118 +            Class<? extends Annotation> koTest = 
 220.119 +                c.getClassLoader().loadClass(KOTest.class.getName()).
 220.120 +                asSubclass(Annotation.class);
 220.121 +            for (Method m : c.getMethods()) {
 220.122 +                if (m.getAnnotation(koTest) != null) {
 220.123 +                    res.add(new TyrusFX(browserContext, m));
 220.124 +                }
 220.125 +            }
 220.126 +        }
 220.127 +        return res.toArray();
 220.128 +    }
 220.129 +
 220.130 +    static synchronized ClassLoader getClassLoader() throws InterruptedException {
 220.131 +        while (browserClass == null) {
 220.132 +            TyrusKnockoutTest.class.wait();
 220.133 +        }
 220.134 +        return browserClass.getClassLoader();
 220.135 +    }
 220.136 +    
 220.137 +    public static synchronized void initialized(Class<?> browserCls) throws Exception {
 220.138 +        browserClass = browserCls;
 220.139 +        browserContext = Fn.activePresenter();
 220.140 +        TyrusKnockoutTest.class.notifyAll();
 220.141 +    }
 220.142 +    
 220.143 +    public static void initialized() throws Exception {
 220.144 +        Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(TyrusKnockoutTest.class.getName());
 220.145 +        Method m = classpathClass.getMethod("initialized", Class.class);
 220.146 +        m.invoke(null, TyrusKnockoutTest.class);
 220.147 +        browserContext = Fn.activePresenter();
 220.148 +    }
 220.149 +    
 220.150 +    @Override
 220.151 +    public BrwsrCtx createContext() {
 220.152 +        FXContext fx = new FXContext(browserContext);
 220.153 +        TyrusContext tc = new TyrusContext();
 220.154 +        Contexts.Builder cb = Contexts.newBuilder().
 220.155 +            register(Technology.class, fx, 10).
 220.156 +            register(Transfer.class, fx, 10).
 220.157 +            register(WSTransfer.class, tc, 10);
 220.158 +        return cb.build();
 220.159 +    }
 220.160 +
 220.161 +    @Override
 220.162 +    public Object createJSON(Map<String, Object> values) {
 220.163 +        JSONObject json = new JSONObject();
 220.164 +        for (Map.Entry<String, Object> entry : values.entrySet()) {
 220.165 +            try {
 220.166 +                json.put(entry.getKey(), entry.getValue());
 220.167 +            } catch (JSONException ex) {
 220.168 +                throw new IllegalStateException(ex);
 220.169 +            }
 220.170 +        }
 220.171 +        return json;
 220.172 +    }
 220.173 +
 220.174 +    @Override
 220.175 +    @JavaScriptBody(args = { "s", "args" }, body = ""
 220.176 +        + "var f = new Function(s); "
 220.177 +        + "return f.apply(null, args);"
 220.178 +    )
 220.179 +    public native Object executeScript(String script, Object[] arguments);
 220.180 +
 220.181 +    @JavaScriptBody(args = {  }, body = 
 220.182 +          "var h;"
 220.183 +        + "if (!!window && !!window.location && !!window.location.href)\n"
 220.184 +        + "  h = window.location.href;\n"
 220.185 +        + "else "
 220.186 +        + "  h = null;"
 220.187 +        + "return h;\n"
 220.188 +    )
 220.189 +    private static native String findBaseURL();
 220.190 +    
 220.191 +    @Override
 220.192 +    public URI prepareURL(String content, String mimeType, String[] parameters) {
 220.193 +        try {
 220.194 +            final URL baseURL = new URL(findBaseURL());
 220.195 +            StringBuilder sb = new StringBuilder();
 220.196 +            sb.append("/dynamic?mimeType=").append(mimeType);
 220.197 +            for (int i = 0; i < parameters.length; i++) {
 220.198 +                sb.append("&param" + i).append("=").append(parameters[i]);
 220.199 +            }
 220.200 +            String mangle = content.replace("\n", "%0a")
 220.201 +                .replace("\"", "\\\"").replace(" ", "%20");
 220.202 +            sb.append("&content=").append(mangle);
 220.203 +
 220.204 +            URL query = new URL(baseURL, sb.toString());
 220.205 +            URLConnection c = query.openConnection();
 220.206 +            BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
 220.207 +            URI connectTo = new URI(br.readLine());
 220.208 +            return connectTo;
 220.209 +        } catch (IOException ex) {
 220.210 +            throw new IllegalStateException(ex);
 220.211 +        } catch (URISyntaxException ex) {
 220.212 +            throw new IllegalStateException(ex);
 220.213 +        }
 220.214 +    }
 220.215 +}
   221.1 --- a/ko-ws-tyrus/src/test/resources/org/apidesign/html/wstyrus/test.html	Thu Dec 19 17:11:01 2013 +0100
   221.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   221.3 @@ -1,34 +0,0 @@
   221.4 -<!--
   221.5 -
   221.6 -    HTML via Java(tm) Language Bindings
   221.7 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   221.8 -
   221.9 -    This program is free software: you can redistribute it and/or modify
  221.10 -    it under the terms of the GNU General Public License as published by
  221.11 -    the Free Software Foundation, version 2 of the License.
  221.12 -
  221.13 -    This program is distributed in the hope that it will be useful,
  221.14 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
  221.15 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  221.16 -    GNU General Public License for more details. apidesign.org
  221.17 -    designates this particular file as subject to the
  221.18 -    "Classpath" exception as provided by apidesign.org
  221.19 -    in the License file that accompanied this code.
  221.20 -
  221.21 -    You should have received a copy of the GNU General Public License
  221.22 -    along with this program. Look for COPYING file in the top folder.
  221.23 -    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  221.24 -
  221.25 --->
  221.26 -<!DOCTYPE html>
  221.27 -<html>
  221.28 -    <head>
  221.29 -        <title>Tyrus WebSockets Execution Harness</title>
  221.30 -        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  221.31 -        <meta name="viewport" content="width=device-width">
  221.32 -    </head>
  221.33 -    <body>
  221.34 -        <h1>Tyrus WebSockets Execution Harness</h1>
  221.35 -    </body>
  221.36 -    <script></script>
  221.37 -</html>
   222.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   222.2 +++ b/ko-ws-tyrus/src/test/resources/org/netbeans/html/wstyrus/test.html	Tue Jan 07 08:21:57 2014 +0100
   222.3 @@ -0,0 +1,56 @@
   222.4 +<!--
   222.5 +
   222.6 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   222.7 +
   222.8 +    Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   222.9 +
  222.10 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  222.11 +    Other names may be trademarks of their respective owners.
  222.12 +
  222.13 +    The contents of this file are subject to the terms of either the GNU
  222.14 +    General Public License Version 2 only ("GPL") or the Common
  222.15 +    Development and Distribution License("CDDL") (collectively, the
  222.16 +    "License"). You may not use this file except in compliance with the
  222.17 +    License. You can obtain a copy of the License at
  222.18 +    http://www.netbeans.org/cddl-gplv2.html
  222.19 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  222.20 +    specific language governing permissions and limitations under the
  222.21 +    License.  When distributing the software, include this License Header
  222.22 +    Notice in each file and include the License file at
  222.23 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  222.24 +    particular file as subject to the "Classpath" exception as provided
  222.25 +    by Oracle in the GPL Version 2 section of the License file that
  222.26 +    accompanied this code. If applicable, add the following below the
  222.27 +    License Header, with the fields enclosed by brackets [] replaced by
  222.28 +    your own identifying information:
  222.29 +    "Portions Copyrighted [year] [name of copyright owner]"
  222.30 +
  222.31 +    Contributor(s):
  222.32 +
  222.33 +    The Original Software is NetBeans. The Initial Developer of the Original
  222.34 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  222.35 +
  222.36 +    If you wish your version of this file to be governed by only the CDDL
  222.37 +    or only the GPL Version 2, indicate your decision by adding
  222.38 +    "[Contributor] elects to include this software in this distribution
  222.39 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
  222.40 +    single choice of license, a recipient has the option to distribute
  222.41 +    your version of this file under either the CDDL, the GPL Version 2 or
  222.42 +    to extend the choice of license to its licensees as provided above.
  222.43 +    However, if you add GPL Version 2 code and therefore, elected the GPL
  222.44 +    Version 2 license, then the option applies only if the new code is
  222.45 +    made subject to such option by the copyright holder.
  222.46 +
  222.47 +-->
  222.48 +<!DOCTYPE html>
  222.49 +<html>
  222.50 +    <head>
  222.51 +        <title>Tyrus WebSockets Execution Harness</title>
  222.52 +        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  222.53 +        <meta name="viewport" content="width=device-width">
  222.54 +    </head>
  222.55 +    <body>
  222.56 +        <h1>Tyrus WebSockets Execution Harness</h1>
  222.57 +    </body>
  222.58 +    <script></script>
  222.59 +</html>
   223.1 --- a/pom.xml	Thu Dec 19 17:11:01 2013 +0100
   223.2 +++ b/pom.xml	Tue Jan 07 08:21:57 2014 +0100
   223.3 @@ -1,8 +1,8 @@
   223.4  <?xml version="1.0" encoding="UTF-8"?>
   223.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">
   223.6    <modelVersion>4.0.0</modelVersion>
   223.7 -  <groupId>org.apidesign</groupId>
   223.8 -  <artifactId>html</artifactId>
   223.9 +  <groupId>org.netbeans.html</groupId>
  223.10 +  <artifactId>pom</artifactId>
  223.11    <version>0.7-SNAPSHOT</version>
  223.12    <packaging>pom</packaging>
  223.13    <name>HTML APIs via Java</name>
  223.14 @@ -16,6 +16,7 @@
  223.15        <netbeans.version>RELEASE73</netbeans.version>
  223.16        <license>COPYING</license>
  223.17        <publicPackages></publicPackages>
  223.18 +      <bundleSymbolicName>${project.artifactId}</bundleSymbolicName>
  223.19    </properties>
  223.20    <modules>
  223.21      <module>json</module>
  223.22 @@ -30,17 +31,19 @@
  223.23      <module>geo</module>
  223.24      <module>ko-ws-tyrus</module>
  223.25      <module>html4j-maven-plugin</module>
  223.26 +    <module>ko-osgi-test</module>
  223.27 +    <module>equinox-agentclass-hook</module>
  223.28    </modules>
  223.29    <licenses>
  223.30        <license>
  223.31 -          <name>GPL-2.0wCPexc</name>
  223.32 -          <url>http://opensource.org/licenses/GPL-2.0</url>
  223.33 +          <name>GPL-2.0wCPexc+CDDL</name>
  223.34 +          <url>http://www.netbeans.org/cddl-gplv2.html</url>
  223.35            <distribution>repo</distribution>
  223.36        </license>
  223.37    </licenses>
  223.38    <organization>
  223.39 -      <name>API Design</name>
  223.40 -      <url>http://apidesign.org</url>
  223.41 +      <name>NetBeans</name>
  223.42 +      <url>http://netbeans.org</url>
  223.43    </organization>
  223.44    <scm>
  223.45        <connection>scm:hg:https://hg.apidesign.org/hg/html~html4j</connection>
  223.46 @@ -92,7 +95,7 @@
  223.47                         <exclude>*</exclude>
  223.48                         <exclude>.*/**</exclude>
  223.49                         <exclude>ko-archetype/src/main/resources/**</exclude>
  223.50 -                       <exclude>ko-fx/src/main/resources/org/apidesign/html/kofx/knockout*.js</exclude>
  223.51 +                       <exclude>ko-fx/src/main/resources/org/netbeans/html/kofx/knockout*.js</exclude>
  223.52                    </excludes>
  223.53                </configuration>
  223.54            </plugin>
  223.55 @@ -140,7 +143,7 @@
  223.56                  <configuration>
  223.57                      <instructions>
  223.58                          <Export-Package>${publicPackages},META-INF.services.*</Export-Package>
  223.59 -                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
  223.60 +                        <Bundle-SymbolicName>${bundleSymbolicName}</Bundle-SymbolicName>
  223.61                      </instructions>
  223.62                  </configuration>
  223.63              </plugin>
   224.1 --- a/sound/pom.xml	Thu Dec 19 17:11:01 2013 +0100
   224.2 +++ b/sound/pom.xml	Tue Jan 07 08:21:57 2014 +0100
   224.3 @@ -2,11 +2,11 @@
   224.4  <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">
   224.5      <modelVersion>4.0.0</modelVersion>
   224.6      <parent>
   224.7 -        <groupId>org.apidesign</groupId>
   224.8 -        <artifactId>html</artifactId>
   224.9 +        <groupId>org.netbeans.html</groupId>
  224.10 +        <artifactId>pom</artifactId>
  224.11          <version>0.7-SNAPSHOT</version>
  224.12      </parent>
  224.13 -    <groupId>org.apidesign.html</groupId>
  224.14 +    <groupId>org.netbeans.html</groupId>
  224.15      <artifactId>net.java.html.sound</artifactId>
  224.16      <version>0.7-SNAPSHOT</version>
  224.17      <packaging>bundle</packaging>
  224.18 @@ -31,7 +31,7 @@
  224.19              <scope>test</scope>
  224.20          </dependency>
  224.21          <dependency>
  224.22 -            <groupId>org.apidesign.html</groupId>
  224.23 +            <groupId>org.netbeans.html</groupId>
  224.24              <artifactId>net.java.html.boot</artifactId>
  224.25              <version>0.7-SNAPSHOT</version>
  224.26              <type>jar</type>
   225.1 --- a/sound/src/main/java/net/java/html/sound/AudioClip.java	Thu Dec 19 17:11:01 2013 +0100
   225.2 +++ b/sound/src/main/java/net/java/html/sound/AudioClip.java	Tue Jan 07 08:21:57 2014 +0100
   225.3 @@ -1,22 +1,44 @@
   225.4  /**
   225.5 - * HTML via Java(tm) Language Bindings
   225.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   225.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   225.8   *
   225.9 - * This program is free software: you can redistribute it and/or modify
  225.10 - * it under the terms of the GNU General Public License as published by
  225.11 - * the Free Software Foundation, version 2 of the License.
  225.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  225.13   *
  225.14 - * This program is distributed in the hope that it will be useful,
  225.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  225.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  225.17 - * GNU General Public License for more details. apidesign.org
  225.18 - * designates this particular file as subject to the
  225.19 - * "Classpath" exception as provided by apidesign.org
  225.20 - * in the License file that accompanied this code.
  225.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  225.22 + * Other names may be trademarks of their respective owners.
  225.23   *
  225.24 - * You should have received a copy of the GNU General Public License
  225.25 - * along with this program. Look for COPYING file in the top folder.
  225.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  225.27 + * The contents of this file are subject to the terms of either the GNU
  225.28 + * General Public License Version 2 only ("GPL") or the Common
  225.29 + * Development and Distribution License("CDDL") (collectively, the
  225.30 + * "License"). You may not use this file except in compliance with the
  225.31 + * License. You can obtain a copy of the License at
  225.32 + * http://www.netbeans.org/cddl-gplv2.html
  225.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  225.34 + * specific language governing permissions and limitations under the
  225.35 + * License.  When distributing the software, include this License Header
  225.36 + * Notice in each file and include the License file at
  225.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  225.38 + * particular file as subject to the "Classpath" exception as provided
  225.39 + * by Oracle in the GPL Version 2 section of the License file that
  225.40 + * accompanied this code. If applicable, add the following below the
  225.41 + * License Header, with the fields enclosed by brackets [] replaced by
  225.42 + * your own identifying information:
  225.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  225.44 + *
  225.45 + * Contributor(s):
  225.46 + *
  225.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  225.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  225.49 + *
  225.50 + * If you wish your version of this file to be governed by only the CDDL
  225.51 + * or only the GPL Version 2, indicate your decision by adding
  225.52 + * "[Contributor] elects to include this software in this distribution
  225.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  225.54 + * single choice of license, a recipient has the option to distribute
  225.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  225.56 + * to extend the choice of license to its licensees as provided above.
  225.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  225.58 + * Version 2 license, then the option applies only if the new code is
  225.59 + * made subject to such option by the copyright holder.
  225.60   */
  225.61  package net.java.html.sound;
  225.62  
   226.1 --- a/sound/src/main/java/org/apidesign/html/sound/impl/BrowserAudioEnv.java	Thu Dec 19 17:11:01 2013 +0100
   226.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   226.3 @@ -1,59 +0,0 @@
   226.4 -/**
   226.5 - * HTML via Java(tm) Language Bindings
   226.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   226.7 - *
   226.8 - * This program is free software: you can redistribute it and/or modify
   226.9 - * it under the terms of the GNU General Public License as published by
  226.10 - * the Free Software Foundation, version 2 of the License.
  226.11 - *
  226.12 - * This program is distributed in the hope that it will be useful,
  226.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  226.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  226.15 - * GNU General Public License for more details. apidesign.org
  226.16 - * designates this particular file as subject to the
  226.17 - * "Classpath" exception as provided by apidesign.org
  226.18 - * in the License file that accompanied this code.
  226.19 - *
  226.20 - * You should have received a copy of the GNU General Public License
  226.21 - * along with this program. Look for COPYING file in the top folder.
  226.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  226.23 - */
  226.24 -package org.apidesign.html.sound.impl;
  226.25 -
  226.26 -import net.java.html.js.JavaScriptBody;
  226.27 -import org.apidesign.html.sound.spi.AudioEnvironment;
  226.28 -import org.openide.util.lookup.ServiceProvider;
  226.29 -
  226.30 -/** Registers an audio provider that delegates to HTML5 Audio tag.
  226.31 - *
  226.32 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  226.33 - */
  226.34 -@ServiceProvider(service = AudioEnvironment.class, position = 100)
  226.35 -public final class BrowserAudioEnv implements AudioEnvironment<Object> {
  226.36 -    @Override
  226.37 -    @JavaScriptBody(args = { "src" }, body = ""
  226.38 -        + "if (!Audio) return null;"
  226.39 -        + "return new Audio(src);")
  226.40 -    public Object create(String src) {
  226.41 -        // null if not running in browser
  226.42 -        return null;
  226.43 -    }
  226.44 -
  226.45 -    @Override @JavaScriptBody(args = { "a" }, body = "a.play();")
  226.46 -    public void play(Object a) {
  226.47 -    }
  226.48 -
  226.49 -    @Override @JavaScriptBody(args = { "a" }, body = "a.pause();")
  226.50 -    public void pause(Object a) {
  226.51 -    }
  226.52 -
  226.53 -    @Override @JavaScriptBody(args = { "a", "volume" }, body = "a.setVolume(volume);")
  226.54 -    public void setVolume(Object a, double volume) {
  226.55 -    }
  226.56 -
  226.57 -    @Override
  226.58 -    @JavaScriptBody(args = "a", body = "return true;")
  226.59 -    public boolean isSupported(Object a) {
  226.60 -        return false;
  226.61 -    }
  226.62 -}
   227.1 --- a/sound/src/main/java/org/apidesign/html/sound/spi/AudioEnvironment.java	Thu Dec 19 17:11:01 2013 +0100
   227.2 +++ b/sound/src/main/java/org/apidesign/html/sound/spi/AudioEnvironment.java	Tue Jan 07 08:21:57 2014 +0100
   227.3 @@ -1,22 +1,44 @@
   227.4  /**
   227.5 - * HTML via Java(tm) Language Bindings
   227.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   227.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   227.8   *
   227.9 - * This program is free software: you can redistribute it and/or modify
  227.10 - * it under the terms of the GNU General Public License as published by
  227.11 - * the Free Software Foundation, version 2 of the License.
  227.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
  227.13   *
  227.14 - * This program is distributed in the hope that it will be useful,
  227.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  227.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  227.17 - * GNU General Public License for more details. apidesign.org
  227.18 - * designates this particular file as subject to the
  227.19 - * "Classpath" exception as provided by apidesign.org
  227.20 - * in the License file that accompanied this code.
  227.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  227.22 + * Other names may be trademarks of their respective owners.
  227.23   *
  227.24 - * You should have received a copy of the GNU General Public License
  227.25 - * along with this program. Look for COPYING file in the top folder.
  227.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  227.27 + * The contents of this file are subject to the terms of either the GNU
  227.28 + * General Public License Version 2 only ("GPL") or the Common
  227.29 + * Development and Distribution License("CDDL") (collectively, the
  227.30 + * "License"). You may not use this file except in compliance with the
  227.31 + * License. You can obtain a copy of the License at
  227.32 + * http://www.netbeans.org/cddl-gplv2.html
  227.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  227.34 + * specific language governing permissions and limitations under the
  227.35 + * License.  When distributing the software, include this License Header
  227.36 + * Notice in each file and include the License file at
  227.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  227.38 + * particular file as subject to the "Classpath" exception as provided
  227.39 + * by Oracle in the GPL Version 2 section of the License file that
  227.40 + * accompanied this code. If applicable, add the following below the
  227.41 + * License Header, with the fields enclosed by brackets [] replaced by
  227.42 + * your own identifying information:
  227.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  227.44 + *
  227.45 + * Contributor(s):
  227.46 + *
  227.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  227.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  227.49 + *
  227.50 + * If you wish your version of this file to be governed by only the CDDL
  227.51 + * or only the GPL Version 2, indicate your decision by adding
  227.52 + * "[Contributor] elects to include this software in this distribution
  227.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  227.54 + * single choice of license, a recipient has the option to distribute
  227.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  227.56 + * to extend the choice of license to its licensees as provided above.
  227.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  227.58 + * Version 2 license, then the option applies only if the new code is
  227.59 + * made subject to such option by the copyright holder.
  227.60   */
  227.61  package org.apidesign.html.sound.spi;
  227.62  
   228.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   228.2 +++ b/sound/src/main/java/org/netbeans/html/sound/impl/BrowserAudioEnv.java	Tue Jan 07 08:21:57 2014 +0100
   228.3 @@ -0,0 +1,81 @@
   228.4 +/**
   228.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   228.6 + *
   228.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
   228.8 + *
   228.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  228.10 + * Other names may be trademarks of their respective owners.
  228.11 + *
  228.12 + * The contents of this file are subject to the terms of either the GNU
  228.13 + * General Public License Version 2 only ("GPL") or the Common
  228.14 + * Development and Distribution License("CDDL") (collectively, the
  228.15 + * "License"). You may not use this file except in compliance with the
  228.16 + * License. You can obtain a copy of the License at
  228.17 + * http://www.netbeans.org/cddl-gplv2.html
  228.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  228.19 + * specific language governing permissions and limitations under the
  228.20 + * License.  When distributing the software, include this License Header
  228.21 + * Notice in each file and include the License file at
  228.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  228.23 + * particular file as subject to the "Classpath" exception as provided
  228.24 + * by Oracle in the GPL Version 2 section of the License file that
  228.25 + * accompanied this code. If applicable, add the following below the
  228.26 + * License Header, with the fields enclosed by brackets [] replaced by
  228.27 + * your own identifying information:
  228.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  228.29 + *
  228.30 + * Contributor(s):
  228.31 + *
  228.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  228.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  228.34 + *
  228.35 + * If you wish your version of this file to be governed by only the CDDL
  228.36 + * or only the GPL Version 2, indicate your decision by adding
  228.37 + * "[Contributor] elects to include this software in this distribution
  228.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  228.39 + * single choice of license, a recipient has the option to distribute
  228.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  228.41 + * to extend the choice of license to its licensees as provided above.
  228.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  228.43 + * Version 2 license, then the option applies only if the new code is
  228.44 + * made subject to such option by the copyright holder.
  228.45 + */
  228.46 +package org.netbeans.html.sound.impl;
  228.47 +
  228.48 +import net.java.html.js.JavaScriptBody;
  228.49 +import org.apidesign.html.sound.spi.AudioEnvironment;
  228.50 +import org.openide.util.lookup.ServiceProvider;
  228.51 +
  228.52 +/** Registers an audio provider that delegates to HTML5 Audio tag.
  228.53 + *
  228.54 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  228.55 + */
  228.56 +@ServiceProvider(service = AudioEnvironment.class, position = 100)
  228.57 +public final class BrowserAudioEnv implements AudioEnvironment<Object> {
  228.58 +    @Override
  228.59 +    @JavaScriptBody(args = { "src" }, body = ""
  228.60 +        + "if (!Audio) return null;"
  228.61 +        + "return new Audio(src);")
  228.62 +    public Object create(String src) {
  228.63 +        // null if not running in browser
  228.64 +        return null;
  228.65 +    }
  228.66 +
  228.67 +    @Override @JavaScriptBody(args = { "a" }, body = "a.play();")
  228.68 +    public void play(Object a) {
  228.69 +    }
  228.70 +
  228.71 +    @Override @JavaScriptBody(args = { "a" }, body = "a.pause();")
  228.72 +    public void pause(Object a) {
  228.73 +    }
  228.74 +
  228.75 +    @Override @JavaScriptBody(args = { "a", "volume" }, body = "a.setVolume(volume);")
  228.76 +    public void setVolume(Object a, double volume) {
  228.77 +    }
  228.78 +
  228.79 +    @Override
  228.80 +    @JavaScriptBody(args = "a", body = "return true;")
  228.81 +    public boolean isSupported(Object a) {
  228.82 +        return false;
  228.83 +    }
  228.84 +}