Merging the rebranding done on the netbeans branch
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 16 Dec 2013 17:16:40 +0100
changeset 3642739565c7a45
parent 363 52c7a3ffcb5f
parent 362 92fb71afdc0e
child 365 5c93ad8c7a15
Merging the rebranding done on the netbeans branch
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/FXPresenterTst.java
boot-fx/src/test/java/org/apidesign/html/boot/fx/KOFx.java
boot-fx/src/test/resources/org/apidesign/html/boot/fx/empty.html
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/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
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/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/resources/org/apidesign/html/wstyrus/test.html
pom.xml
sound/src/main/java/org/apidesign/html/sound/impl/BrowserAudioEnv.java
     1.1 --- a/COPYING	Mon Dec 16 17:16:02 2013 +0100
     1.2 +++ b/COPYING	Mon Dec 16 17:16:40 2013 +0100
     1.3 @@ -1,18 +1,40 @@
     1.4 -HTML via Java(tm) Language Bindings
     1.5 -Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     1.6 +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     1.7  
     1.8 -This program is free software: you can redistribute it and/or modify
     1.9 -it under the terms of the GNU General Public License as published by
    1.10 -the Free Software Foundation, version 2 of the License.
    1.11 +Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    1.12  
    1.13 -This program is distributed in the hope that it will be useful,
    1.14 -but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.16 -GNU General Public License for more details. apidesign.org 
    1.17 -designates this particular file as subject to the 
    1.18 -"Classpath" exception as provided by apidesign.org 
    1.19 -in the License file that accompanied this code.
    1.20 +Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    1.21 +Other names may be trademarks of their respective owners.
    1.22  
    1.23 -You should have received a copy of the GNU General Public License
    1.24 -along with this program. Look for COPYING file in the top folder.
    1.25 -If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    1.26 +The contents of this file are subject to the terms of either the GNU
    1.27 +General Public License Version 2 only ("GPL") or the Common
    1.28 +Development and Distribution License("CDDL") (collectively, the
    1.29 +"License"). You may not use this file except in compliance with the
    1.30 +License. You can obtain a copy of the License at
    1.31 +http://www.netbeans.org/cddl-gplv2.html
    1.32 +or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    1.33 +specific language governing permissions and limitations under the
    1.34 +License.  When distributing the software, include this License Header
    1.35 +Notice in each file and include the License file at
    1.36 +nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    1.37 +particular file as subject to the "Classpath" exception as provided
    1.38 +by Oracle in the GPL Version 2 section of the License file that
    1.39 +accompanied this code. If applicable, add the following below the
    1.40 +License Header, with the fields enclosed by brackets [] replaced by
    1.41 +your own identifying information:
    1.42 +"Portions Copyrighted [year] [name of copyright owner]"
    1.43 +
    1.44 +Contributor(s):
    1.45 +
    1.46 +The Original Software is NetBeans. The Initial Developer of the Original
    1.47 +Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
    1.48 +
    1.49 +If you wish your version of this file to be governed by only the CDDL
    1.50 +or only the GPL Version 2, indicate your decision by adding
    1.51 +"[Contributor] elects to include this software in this distribution
    1.52 +under the [CDDL or GPL Version 2] license." If you do not indicate a
    1.53 +single choice of license, a recipient has the option to distribute
    1.54 +your version of this file under either the CDDL, the GPL Version 2 or
    1.55 +to extend the choice of license to its licensees as provided above.
    1.56 +However, if you add GPL Version 2 code and therefore, elected the GPL
    1.57 +Version 2 license, then the option applies only if the new code is
    1.58 +made subject to such option by the copyright holder.
     2.1 --- a/boot-fx/pom.xml	Mon Dec 16 17:16:02 2013 +0100
     2.2 +++ b/boot-fx/pom.xml	Mon Dec 16 17:16:40 2013 +0100
     2.3 @@ -2,12 +2,12 @@
     2.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">
     2.5    <modelVersion>4.0.0</modelVersion>
     2.6    <parent>
     2.7 -    <groupId>org.apidesign</groupId>
     2.8 -    <artifactId>html</artifactId>
     2.9 +    <groupId>org.netbeans.html</groupId>
    2.10 +    <artifactId>pom</artifactId>
    2.11      <version>0.7-SNAPSHOT</version>
    2.12    </parent>
    2.13 -  <groupId>org.apidesign.html</groupId>
    2.14 -  <artifactId>boot-fx</artifactId>
    2.15 +  <groupId>org.netbeans.html</groupId>
    2.16 +  <artifactId>net.java.html.boot.fx</artifactId>
    2.17    <version>0.7-SNAPSHOT</version>
    2.18    <name>FX WebView Bootstrap</name>
    2.19    <packaging>bundle</packaging>
    2.20 @@ -54,7 +54,7 @@
    2.21        <scope>provided</scope>
    2.22      </dependency>
    2.23      <dependency>
    2.24 -      <groupId>org.apidesign.html</groupId>
    2.25 +      <groupId>org.netbeans.html</groupId>
    2.26        <artifactId>net.java.html.boot</artifactId>
    2.27        <version>${project.version}</version>
    2.28        <type>jar</type>
     3.1 --- a/boot-fx/src/main/java/net/java/html/boot/fx/FXBrowsers.java	Mon Dec 16 17:16:02 2013 +0100
     3.2 +++ b/boot-fx/src/main/java/net/java/html/boot/fx/FXBrowsers.java	Mon Dec 16 17:16:40 2013 +0100
     3.3 @@ -1,22 +1,44 @@
     3.4  /**
     3.5 - * HTML via Java(tm) Language Bindings
     3.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     3.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3.8   *
     3.9 - * This program is free software: you can redistribute it and/or modify
    3.10 - * it under the terms of the GNU General Public License as published by
    3.11 - * the Free Software Foundation, version 2 of the License.
    3.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    3.13   *
    3.14 - * This program is distributed in the hope that it will be useful,
    3.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.17 - * GNU General Public License for more details. apidesign.org
    3.18 - * designates this particular file as subject to the
    3.19 - * "Classpath" exception as provided by apidesign.org
    3.20 - * in the License file that accompanied this code.
    3.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    3.22 + * Other names may be trademarks of their respective owners.
    3.23   *
    3.24 - * You should have received a copy of the GNU General Public License
    3.25 - * along with this program. Look for COPYING file in the top folder.
    3.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    3.27 + * The contents of this file are subject to the terms of either the GNU
    3.28 + * General Public License Version 2 only ("GPL") or the Common
    3.29 + * Development and Distribution License("CDDL") (collectively, the
    3.30 + * "License"). You may not use this file except in compliance with the
    3.31 + * License. You can obtain a copy of the License at
    3.32 + * http://www.netbeans.org/cddl-gplv2.html
    3.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    3.34 + * specific language governing permissions and limitations under the
    3.35 + * License.  When distributing the software, include this License Header
    3.36 + * Notice in each file and include the License file at
    3.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    3.38 + * particular file as subject to the "Classpath" exception as provided
    3.39 + * by Oracle in the GPL Version 2 section of the License file that
    3.40 + * accompanied this code. If applicable, add the following below the
    3.41 + * License Header, with the fields enclosed by brackets [] replaced by
    3.42 + * your own identifying information:
    3.43 + * "Portions Copyrighted [year] [name of copyright owner]"
    3.44 + *
    3.45 + * Contributor(s):
    3.46 + *
    3.47 + * The Original Software is NetBeans. The Initial Developer of the Original
    3.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
    3.49 + *
    3.50 + * If you wish your version of this file to be governed by only the CDDL
    3.51 + * or only the GPL Version 2, indicate your decision by adding
    3.52 + * "[Contributor] elects to include this software in this distribution
    3.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    3.54 + * single choice of license, a recipient has the option to distribute
    3.55 + * your version of this file under either the CDDL, the GPL Version 2 or
    3.56 + * to extend the choice of license to its licensees as provided above.
    3.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    3.58 + * Version 2 license, then the option applies only if the new code is
    3.59 + * made subject to such option by the copyright holder.
    3.60   */
    3.61  package net.java.html.boot.fx;
    3.62  
    3.63 @@ -27,7 +49,7 @@
    3.64  import javafx.scene.web.WebView;
    3.65  import net.java.html.boot.BrowserBuilder;
    3.66  import net.java.html.js.JavaScriptBody;
    3.67 -import org.apidesign.html.boot.fx.AbstractFXPresenter;
    3.68 +import org.netbeans.html.boot.fx.AbstractFXPresenter;
    3.69  
    3.70  /** Utility methods for working with <em>JavaFX</em> <code>WebView</code>s.
    3.71   *
     4.1 --- a/boot-fx/src/main/java/org/apidesign/html/boot/fx/AbstractFXPresenter.java	Mon Dec 16 17:16:02 2013 +0100
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,168 +0,0 @@
     4.4 -/**
     4.5 - * HTML via Java(tm) Language Bindings
     4.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4.7 - *
     4.8 - * This program is free software: you can redistribute it and/or modify
     4.9 - * it under the terms of the GNU General Public License as published by
    4.10 - * the Free Software Foundation, version 2 of the License.
    4.11 - *
    4.12 - * This program is distributed in the hope that it will be useful,
    4.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.15 - * GNU General Public License for more details. apidesign.org
    4.16 - * designates this particular file as subject to the
    4.17 - * "Classpath" exception as provided by apidesign.org
    4.18 - * in the License file that accompanied this code.
    4.19 - *
    4.20 - * You should have received a copy of the GNU General Public License
    4.21 - * along with this program. Look for COPYING file in the top folder.
    4.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    4.23 - */
    4.24 -package org.apidesign.html.boot.fx;
    4.25 -
    4.26 -import java.io.BufferedReader;
    4.27 -import java.io.Reader;
    4.28 -import java.net.URL;
    4.29 -import java.util.ArrayList;
    4.30 -import java.util.Arrays;
    4.31 -import java.util.List;
    4.32 -import java.util.logging.Level;
    4.33 -import java.util.logging.Logger;
    4.34 -import javafx.application.Platform;
    4.35 -import javafx.scene.web.WebEngine;
    4.36 -import javafx.scene.web.WebView;
    4.37 -import netscape.javascript.JSObject;
    4.38 -import org.apidesign.html.boot.spi.Fn;
    4.39 -
    4.40 -/**
    4.41 - *
    4.42 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    4.43 - */
    4.44 -public abstract class AbstractFXPresenter implements Fn.Presenter {
    4.45 -    static final Logger LOG = Logger.getLogger(FXPresenter.class.getName());
    4.46 -    protected static int cnt;
    4.47 -    protected List<String> scripts;
    4.48 -    protected Runnable onLoad;
    4.49 -    protected WebEngine engine;
    4.50 -
    4.51 -    @Override
    4.52 -    public Fn defineFn(String code, String... names) {
    4.53 -        StringBuilder sb = new StringBuilder();
    4.54 -        sb.append("(function() {");
    4.55 -        sb.append("  return function(");
    4.56 -        String sep = "";
    4.57 -        for (String n : names) {
    4.58 -            sb.append(sep).append(n);
    4.59 -            sep = ",";
    4.60 -        }
    4.61 -        sb.append(") {\n");
    4.62 -        sb.append(code);
    4.63 -        sb.append("};");
    4.64 -        sb.append("})()");
    4.65 -        if (LOG.isLoggable(Level.FINE)) {
    4.66 -            LOG.log(Level.FINE, 
    4.67 -                "defining function #{0}:\n{1}\n", 
    4.68 -                new Object[] { ++cnt, code }
    4.69 -            );
    4.70 -        }
    4.71 -        JSObject x = (JSObject) engine.executeScript(sb.toString());
    4.72 -        return new JSFn(this, x, cnt);
    4.73 -    }
    4.74 -
    4.75 -    @Override
    4.76 -    public void loadScript(Reader code) throws Exception {
    4.77 -        BufferedReader r = new BufferedReader(code);
    4.78 -        StringBuilder sb = new StringBuilder();
    4.79 -        for (;;) {
    4.80 -            String l = r.readLine();
    4.81 -            if (l == null) {
    4.82 -                break;
    4.83 -            }
    4.84 -            sb.append(l).append('\n');
    4.85 -        }
    4.86 -        final String script = sb.toString();
    4.87 -        if (scripts != null) {
    4.88 -            scripts.add(script);
    4.89 -        }
    4.90 -        engine.executeScript(script);
    4.91 -    }
    4.92 -
    4.93 -    protected final void onPageLoad() {
    4.94 -        if (scripts != null) {
    4.95 -            for (String s : scripts) {
    4.96 -                engine.executeScript(s);
    4.97 -            }
    4.98 -        }
    4.99 -        onLoad.run();
   4.100 -    }
   4.101 -
   4.102 -    @Override
   4.103 -    public void displayPage(final URL resource, final Runnable onLoad) {
   4.104 -        this.onLoad = onLoad;
   4.105 -        final WebView view = findView(resource);
   4.106 -        this.engine = view.getEngine();
   4.107 -        try {
   4.108 -            if (FXInspect.initialize(engine)) {
   4.109 -                scripts = new ArrayList<String>();
   4.110 -            }
   4.111 -        } catch (Throwable ex) {
   4.112 -            ex.printStackTrace();
   4.113 -        }
   4.114 -
   4.115 -        class Run implements Runnable {
   4.116 -
   4.117 -            @Override
   4.118 -            public void run() {
   4.119 -                if (scripts != null) {
   4.120 -                    view.setContextMenuEnabled(true);
   4.121 -                }
   4.122 -                engine.load(resource.toExternalForm());
   4.123 -            }
   4.124 -        }
   4.125 -        Run run = new Run();
   4.126 -        if (Platform.isFxApplicationThread()) {
   4.127 -            run.run();
   4.128 -        } else {
   4.129 -            Platform.runLater(run);
   4.130 -        }
   4.131 -        waitFinished();
   4.132 -    }
   4.133 -
   4.134 -    protected abstract void waitFinished();
   4.135 -
   4.136 -    protected abstract WebView findView(final URL resource);
   4.137 -
   4.138 -    private static final class JSFn extends Fn {
   4.139 -
   4.140 -        private final JSObject fn;
   4.141 -        private static int call;
   4.142 -        private final int id;
   4.143 -
   4.144 -        public JSFn(AbstractFXPresenter p, JSObject fn, int id) {
   4.145 -            super(p);
   4.146 -            this.fn = fn;
   4.147 -            this.id = id;
   4.148 -        }
   4.149 -
   4.150 -        @Override
   4.151 -        public Object invoke(Object thiz, Object... args) throws Exception {
   4.152 -            try {
   4.153 -                if (LOG.isLoggable(Level.FINE)) {
   4.154 -                    LOG.log(Level.FINE, "calling {0} function #{1}", new Object[]{++call, id});
   4.155 -                }
   4.156 -                List<Object> all = new ArrayList<Object>(args.length + 1);
   4.157 -                all.add(thiz == null ? fn : thiz);
   4.158 -                all.addAll(Arrays.asList(args));
   4.159 -                Object ret = fn.call("call", all.toArray()); // NOI18N
   4.160 -                return ret == fn ? null : ret;
   4.161 -            } catch (Error t) {
   4.162 -                t.printStackTrace();
   4.163 -                throw t;
   4.164 -            } catch (Exception t) {
   4.165 -                t.printStackTrace();
   4.166 -                throw t;
   4.167 -            }
   4.168 -        }
   4.169 -    }
   4.170 -    
   4.171 -}
     5.1 --- a/boot-fx/src/main/java/org/apidesign/html/boot/fx/Dbgr.java	Mon Dec 16 17:16:02 2013 +0100
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,66 +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 -
    5.25 -package org.apidesign.html.boot.fx;
    5.26 -
    5.27 -import java.lang.reflect.Method;
    5.28 -import java.util.logging.Level;
    5.29 -import javafx.scene.web.WebEngine;
    5.30 -import javafx.util.Callback;
    5.31 -import static org.apidesign.html.boot.fx.AbstractFXPresenter.LOG;
    5.32 -
    5.33 -/** Debugger bridge to shield us from propriatory impl APIs.
    5.34 - *
    5.35 - * @author Jaroslav Tulach <jtulach@netbeans.org>
    5.36 - */
    5.37 -final class Dbgr {
    5.38 -    final Object dbg;
    5.39 -    final Method sendMsg;
    5.40 -    
    5.41 -    Dbgr(WebEngine eng, Callback<String,Void> callback) {
    5.42 -        Object d;
    5.43 -        Method m;
    5.44 -        try {
    5.45 -            d = eng.getClass().getMethod("impl_getDebugger").invoke(eng); // NOI18N
    5.46 -            Class<?> debugger = eng.getClass().getClassLoader().loadClass("com.sun.javafx.scene.web.Debugger"); // NOI18N
    5.47 -            debugger.getMethod("setEnabled", boolean.class).invoke(d, true); // NOI18N
    5.48 -            debugger.getMethod("setMessageCallback", Callback.class).invoke(d, callback); // NOI18N
    5.49 -            m = debugger.getMethod("sendMessage", String.class); // NOI18N
    5.50 -        } catch (Exception ex) {
    5.51 -            LOG.log(Level.INFO, null, ex);
    5.52 -            d = null;
    5.53 -            m = null;
    5.54 -        }
    5.55 -        dbg = d;
    5.56 -        sendMsg = m;
    5.57 -    }
    5.58 -
    5.59 -    void sendMessage(String msg) {
    5.60 -        try {
    5.61 -            if (dbg != null) {
    5.62 -                sendMsg.invoke(dbg, msg);
    5.63 -            }
    5.64 -        } catch (Exception ex) {
    5.65 -            LOG.log(Level.INFO, null, ex);
    5.66 -        }
    5.67 -    }
    5.68 -    
    5.69 -}
     6.1 --- a/boot-fx/src/main/java/org/apidesign/html/boot/fx/FXBrwsr.java	Mon Dec 16 17:16:02 2013 +0100
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,171 +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 -package org.apidesign.html.boot.fx;
    6.25 -
    6.26 -import java.net.URL;
    6.27 -import java.util.concurrent.CountDownLatch;
    6.28 -import java.util.concurrent.Executors;
    6.29 -import java.util.logging.Level;
    6.30 -import java.util.logging.Logger;
    6.31 -import javafx.application.Application;
    6.32 -import javafx.application.Platform;
    6.33 -import javafx.beans.value.ChangeListener;
    6.34 -import javafx.beans.value.ObservableValue;
    6.35 -import javafx.concurrent.Worker;
    6.36 -import javafx.event.ActionEvent;
    6.37 -import javafx.event.EventHandler;
    6.38 -import javafx.geometry.Insets;
    6.39 -import javafx.geometry.Pos;
    6.40 -import javafx.scene.Scene;
    6.41 -import javafx.scene.control.Button;
    6.42 -import javafx.scene.layout.BorderPane;
    6.43 -import javafx.scene.layout.VBox;
    6.44 -import javafx.scene.text.Text;
    6.45 -import javafx.scene.web.WebEvent;
    6.46 -import javafx.scene.web.WebView;
    6.47 -import javafx.stage.Modality;
    6.48 -import javafx.stage.Stage;
    6.49 -
    6.50 -/** This is an implementation class, use {@link BrowserBuilder} API. Just
    6.51 - * include this JAR on classpath and the {@link BrowserBuilder} API will find
    6.52 - * this implementation automatically.
    6.53 - */
    6.54 -public class FXBrwsr extends Application {
    6.55 -    private static final Logger LOG = Logger.getLogger(FXBrwsr.class.getName());
    6.56 -    private static FXBrwsr INSTANCE;
    6.57 -    private static final CountDownLatch FINISHED = new CountDownLatch(1);
    6.58 -    private BorderPane root;
    6.59 -
    6.60 -    public static synchronized WebView findWebView(final URL url, final FXPresenter onLoad) {
    6.61 -        if (INSTANCE == null) {
    6.62 -            Executors.newFixedThreadPool(1).submit(new Runnable() {
    6.63 -                @Override
    6.64 -                public void run() {
    6.65 -                    try {
    6.66 -                        FXBrwsr.launch(FXBrwsr.class);
    6.67 -                    } catch (Throwable ex) {
    6.68 -                        ex.printStackTrace();
    6.69 -                    } finally {
    6.70 -                        FINISHED.countDown();
    6.71 -                    }
    6.72 -                }
    6.73 -            });
    6.74 -        }
    6.75 -        while (INSTANCE == null) {
    6.76 -            try {
    6.77 -                FXBrwsr.class.wait();
    6.78 -            } catch (InterruptedException ex) {
    6.79 -                // wait more
    6.80 -            }
    6.81 -        }
    6.82 -        if (!Platform.isFxApplicationThread()) {
    6.83 -            final WebView[] arr = {null};
    6.84 -            final CountDownLatch waitForResult = new CountDownLatch(1);
    6.85 -            Platform.runLater(new Runnable() {
    6.86 -                @Override
    6.87 -                public void run() {
    6.88 -                    arr[0] = INSTANCE.newView(url, onLoad);
    6.89 -                    waitForResult.countDown();
    6.90 -                }
    6.91 -            });
    6.92 -            for (;;) {
    6.93 -                try {
    6.94 -                    waitForResult.await();
    6.95 -                    break;
    6.96 -                } catch (InterruptedException ex) {
    6.97 -                    LOG.log(Level.INFO, null, ex);
    6.98 -                }
    6.99 -            }
   6.100 -            return arr[0];
   6.101 -        } else {
   6.102 -            return INSTANCE.newView(url, onLoad);
   6.103 -        }
   6.104 -    }
   6.105 -
   6.106 -    @Override
   6.107 -    public void start(Stage primaryStage) throws Exception {
   6.108 -        synchronized (FXBrwsr.class) {
   6.109 -            INSTANCE = this;
   6.110 -            FXBrwsr.class.notifyAll();
   6.111 -        }
   6.112 -        BorderPane r = new BorderPane();
   6.113 -        Scene scene = new Scene(r, 800, 600);
   6.114 -        primaryStage.setScene(scene);
   6.115 -        primaryStage.show();
   6.116 -        this.root = r;
   6.117 -    }
   6.118 -
   6.119 -    private WebView newView(final URL url, final FXPresenter onLoad) {
   6.120 -        final WebView view = new WebView();
   6.121 -        view.setContextMenuEnabled(false);
   6.122 -        view.getEngine().setOnAlert(new EventHandler<WebEvent<String>>() {
   6.123 -            @Override
   6.124 -            public void handle(WebEvent<String> t) {
   6.125 -                final Stage dialogStage = new Stage();
   6.126 -                dialogStage.initModality(Modality.WINDOW_MODAL);
   6.127 -                dialogStage.setTitle("Warning");
   6.128 -                final Button button = new Button("Close");
   6.129 -                final Text text = new Text(t.getData());
   6.130 -                VBox box = new VBox();
   6.131 -                box.setAlignment(Pos.CENTER);
   6.132 -                box.setSpacing(10);
   6.133 -                box.setPadding(new Insets(10));
   6.134 -                box.getChildren().addAll(text, button);
   6.135 -                dialogStage.setScene(new Scene(box));
   6.136 -                button.setCancelButton(true);
   6.137 -                button.setOnAction(new EventHandler<ActionEvent>() {
   6.138 -                    @Override
   6.139 -                    public void handle(ActionEvent t) {
   6.140 -                        dialogStage.close();
   6.141 -                    }
   6.142 -                });
   6.143 -                dialogStage.centerOnScreen();
   6.144 -                dialogStage.showAndWait();
   6.145 -            }
   6.146 -        });
   6.147 -        root.setCenter(view);
   6.148 -        final Worker<Void> w = view.getEngine().getLoadWorker();
   6.149 -        w.stateProperty().addListener(new ChangeListener<Worker.State>() {
   6.150 -            @Override
   6.151 -            public void changed(ObservableValue<? extends Worker.State> ov, Worker.State t, Worker.State newState) {
   6.152 -                if (newState.equals(Worker.State.SUCCEEDED)) {
   6.153 -                    onLoad.onPageLoad();
   6.154 -                }
   6.155 -                if (newState.equals(Worker.State.FAILED)) {
   6.156 -                    throw new IllegalStateException("Failed to load " + url);
   6.157 -                }
   6.158 -            }
   6.159 -        });
   6.160 -        return view;
   6.161 -    }
   6.162 -
   6.163 -    static void waitFinished() {
   6.164 -        for (;;) {
   6.165 -            try {
   6.166 -                FINISHED.await();
   6.167 -                break;
   6.168 -            } catch (InterruptedException ex) {
   6.169 -                LOG.log(Level.INFO, null, ex);
   6.170 -            }
   6.171 -        }
   6.172 -    }
   6.173 -    
   6.174 -}
     7.1 --- a/boot-fx/src/main/java/org/apidesign/html/boot/fx/FXInspect.java	Mon Dec 16 17:16:02 2013 +0100
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,112 +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.io.IOException;
    7.27 -import java.io.ObjectInputStream;
    7.28 -import java.io.ObjectOutputStream;
    7.29 -import java.net.InetAddress;
    7.30 -import java.net.Socket;
    7.31 -import java.nio.charset.StandardCharsets;
    7.32 -import java.util.logging.Level;
    7.33 -import java.util.logging.Logger;
    7.34 -import javafx.application.Platform;
    7.35 -import javafx.scene.web.WebEngine;
    7.36 -import javafx.util.Callback;
    7.37 -
    7.38 -/**
    7.39 - *
    7.40 - * @author Jaroslav Tulach <jtulach@netbeans.org>
    7.41 - */
    7.42 -final class FXInspect implements Runnable {
    7.43 -    private static final Logger LOG = Logger.getLogger(FXInspect.class.getName());
    7.44 -    
    7.45 -    
    7.46 -    private final WebEngine engine;
    7.47 -    private final ObjectInputStream input;
    7.48 -    private Dbgr dbg;
    7.49 -    
    7.50 -    private FXInspect(WebEngine engine, int port) throws IOException {
    7.51 -        this.engine = engine;
    7.52 -        
    7.53 -        Socket socket = new Socket(InetAddress.getByName(null), port);
    7.54 -        ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
    7.55 -        this.input = new ObjectInputStream(socket.getInputStream());
    7.56 -        initializeDebugger(output);
    7.57 -    }
    7.58 -    
    7.59 -    static boolean initialize(WebEngine engine) {
    7.60 -        final int inspectPort = Integer.getInteger("netbeans.inspect.port", -1); // NOI18N
    7.61 -        if (inspectPort != -1) {
    7.62 -            try {
    7.63 -                FXInspect inspector = new FXInspect(engine, inspectPort);
    7.64 -                Thread t = new Thread(inspector, "FX<->NetBeans Inspector");
    7.65 -                t.start();
    7.66 -                return true;
    7.67 -            } catch (IOException ex) {
    7.68 -                LOG.log(Level.INFO, "Cannot connect to NetBeans IDE to port " + inspectPort, ex); // NOI18N
    7.69 -            }
    7.70 -        }
    7.71 -        return false;
    7.72 -    }
    7.73 -    
    7.74 -    private void initializeDebugger(final ObjectOutputStream output) {
    7.75 -        Platform.runLater(new Runnable() {
    7.76 -            @Override
    7.77 -            public void run() {
    7.78 -                dbg = new Dbgr(engine, new Callback<String,Void>() {
    7.79 -                    @Override
    7.80 -                    public Void call(String message) {
    7.81 -                        try {
    7.82 -                            byte[] bytes = message.getBytes(StandardCharsets.UTF_8);
    7.83 -                            output.writeInt(bytes.length);
    7.84 -                            output.write(bytes);
    7.85 -                            output.flush();
    7.86 -                        } catch (IOException ioex) {
    7.87 -                            ioex.printStackTrace();
    7.88 -                        }
    7.89 -                        return null;
    7.90 -                    }
    7.91 -                });
    7.92 -            }
    7.93 -        });
    7.94 -    }
    7.95 -
    7.96 -    @Override
    7.97 -    public void run() {
    7.98 -        try {
    7.99 -            while (true) {
   7.100 -                int length = input.readInt();
   7.101 -                byte[] bytes = new byte[length];
   7.102 -                input.readFully(bytes);
   7.103 -                final String message = new String(bytes, StandardCharsets.UTF_8);
   7.104 -                Platform.runLater(new Runnable() {
   7.105 -                    @Override
   7.106 -                    public void run() {
   7.107 -                        dbg.sendMessage(message);
   7.108 -                    }
   7.109 -                });
   7.110 -            }
   7.111 -        } catch (IOException ex) {
   7.112 -            LOG.log(Level.WARNING, null, ex);
   7.113 -        }
   7.114 -    }
   7.115 -}
     8.1 --- a/boot-fx/src/main/java/org/apidesign/html/boot/fx/FXPresenter.java	Mon Dec 16 17:16:02 2013 +0100
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,76 +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.BufferedReader;
    8.27 -import java.io.File;
    8.28 -import java.io.Reader;
    8.29 -import java.lang.reflect.Method;
    8.30 -import java.net.URL;
    8.31 -import java.net.URLClassLoader;
    8.32 -import java.util.ArrayList;
    8.33 -import java.util.Arrays;
    8.34 -import java.util.List;
    8.35 -import java.util.logging.Level;
    8.36 -import java.util.logging.Logger;
    8.37 -import javafx.application.Platform;
    8.38 -import javafx.scene.web.WebEngine;
    8.39 -import javafx.scene.web.WebView;
    8.40 -import net.java.html.boot.BrowserBuilder;
    8.41 -import netscape.javascript.JSObject;
    8.42 -import org.apidesign.html.boot.spi.Fn;
    8.43 -import org.openide.util.lookup.ServiceProvider;
    8.44 -
    8.45 -/** This is an implementation class, use {@link BrowserBuilder} API. Just
    8.46 - * include this JAR on classpath and the {@link BrowserBuilder} API will find
    8.47 - * this implementation automatically.
    8.48 - *
    8.49 - * @author Jaroslav Tulach <jtulach@netbeans.org>
    8.50 - */
    8.51 -@ServiceProvider(service = Fn.Presenter.class)
    8.52 -public final class FXPresenter extends AbstractFXPresenter {
    8.53 -    static {
    8.54 -        try {
    8.55 -            try {
    8.56 -                Class<?> c = Class.forName("javafx.application.Platform");
    8.57 -                // OK, on classpath
    8.58 -            } catch (ClassNotFoundException classNotFoundException) {
    8.59 -                Method m = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
    8.60 -                m.setAccessible(true);
    8.61 -                File f = new File(System.getProperty("java.home"), "lib/jfxrt.jar");
    8.62 -                if (f.exists()) {
    8.63 -                    URL l = f.toURI().toURL();
    8.64 -                    m.invoke(ClassLoader.getSystemClassLoader(), l);
    8.65 -                }
    8.66 -            }
    8.67 -        } catch (Exception ex) {
    8.68 -            throw new LinkageError("Can't add jfxrt.jar on the classpath", ex);
    8.69 -        }
    8.70 -    }
    8.71 -
    8.72 -    protected void waitFinished() {
    8.73 -        FXBrwsr.waitFinished();
    8.74 -    }
    8.75 -
    8.76 -    protected WebView findView(final URL resource) {
    8.77 -        return FXBrwsr.findWebView(resource, this);
    8.78 -    }
    8.79 -}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/AbstractFXPresenter.java	Mon Dec 16 17:16:40 2013 +0100
     9.3 @@ -0,0 +1,190 @@
     9.4 +/**
     9.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     9.6 + *
     9.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
     9.8 + *
     9.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    9.10 + * Other names may be trademarks of their respective owners.
    9.11 + *
    9.12 + * The contents of this file are subject to the terms of either the GNU
    9.13 + * General Public License Version 2 only ("GPL") or the Common
    9.14 + * Development and Distribution License("CDDL") (collectively, the
    9.15 + * "License"). You may not use this file except in compliance with the
    9.16 + * License. You can obtain a copy of the License at
    9.17 + * http://www.netbeans.org/cddl-gplv2.html
    9.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    9.19 + * specific language governing permissions and limitations under the
    9.20 + * License.  When distributing the software, include this License Header
    9.21 + * Notice in each file and include the License file at
    9.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    9.23 + * particular file as subject to the "Classpath" exception as provided
    9.24 + * by Oracle in the GPL Version 2 section of the License file that
    9.25 + * accompanied this code. If applicable, add the following below the
    9.26 + * License Header, with the fields enclosed by brackets [] replaced by
    9.27 + * your own identifying information:
    9.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    9.29 + *
    9.30 + * Contributor(s):
    9.31 + *
    9.32 + * The Original Software is NetBeans. The Initial Developer of the Original
    9.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
    9.34 + *
    9.35 + * If you wish your version of this file to be governed by only the CDDL
    9.36 + * or only the GPL Version 2, indicate your decision by adding
    9.37 + * "[Contributor] elects to include this software in this distribution
    9.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    9.39 + * single choice of license, a recipient has the option to distribute
    9.40 + * your version of this file under either the CDDL, the GPL Version 2 or
    9.41 + * to extend the choice of license to its licensees as provided above.
    9.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    9.43 + * Version 2 license, then the option applies only if the new code is
    9.44 + * made subject to such option by the copyright holder.
    9.45 + */
    9.46 +package org.netbeans.html.boot.fx;
    9.47 +
    9.48 +import java.io.BufferedReader;
    9.49 +import java.io.Reader;
    9.50 +import java.net.URL;
    9.51 +import java.util.ArrayList;
    9.52 +import java.util.Arrays;
    9.53 +import java.util.List;
    9.54 +import java.util.logging.Level;
    9.55 +import java.util.logging.Logger;
    9.56 +import javafx.application.Platform;
    9.57 +import javafx.scene.web.WebEngine;
    9.58 +import javafx.scene.web.WebView;
    9.59 +import netscape.javascript.JSObject;
    9.60 +import org.apidesign.html.boot.spi.Fn;
    9.61 +
    9.62 +/**
    9.63 + *
    9.64 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    9.65 + */
    9.66 +public abstract class AbstractFXPresenter implements Fn.Presenter {
    9.67 +    static final Logger LOG = Logger.getLogger(FXPresenter.class.getName());
    9.68 +    protected static int cnt;
    9.69 +    protected List<String> scripts;
    9.70 +    protected Runnable onLoad;
    9.71 +    protected WebEngine engine;
    9.72 +
    9.73 +    @Override
    9.74 +    public Fn defineFn(String code, String... names) {
    9.75 +        StringBuilder sb = new StringBuilder();
    9.76 +        sb.append("(function() {");
    9.77 +        sb.append("  return function(");
    9.78 +        String sep = "";
    9.79 +        for (String n : names) {
    9.80 +            sb.append(sep).append(n);
    9.81 +            sep = ",";
    9.82 +        }
    9.83 +        sb.append(") {\n");
    9.84 +        sb.append(code);
    9.85 +        sb.append("};");
    9.86 +        sb.append("})()");
    9.87 +        if (LOG.isLoggable(Level.FINE)) {
    9.88 +            LOG.log(Level.FINE, 
    9.89 +                "defining function #{0}:\n{1}\n", 
    9.90 +                new Object[] { ++cnt, code }
    9.91 +            );
    9.92 +        }
    9.93 +        JSObject x = (JSObject) engine.executeScript(sb.toString());
    9.94 +        return new JSFn(this, x, cnt);
    9.95 +    }
    9.96 +
    9.97 +    @Override
    9.98 +    public void loadScript(Reader code) throws Exception {
    9.99 +        BufferedReader r = new BufferedReader(code);
   9.100 +        StringBuilder sb = new StringBuilder();
   9.101 +        for (;;) {
   9.102 +            String l = r.readLine();
   9.103 +            if (l == null) {
   9.104 +                break;
   9.105 +            }
   9.106 +            sb.append(l).append('\n');
   9.107 +        }
   9.108 +        final String script = sb.toString();
   9.109 +        if (scripts != null) {
   9.110 +            scripts.add(script);
   9.111 +        }
   9.112 +        engine.executeScript(script);
   9.113 +    }
   9.114 +
   9.115 +    protected final void onPageLoad() {
   9.116 +        if (scripts != null) {
   9.117 +            for (String s : scripts) {
   9.118 +                engine.executeScript(s);
   9.119 +            }
   9.120 +        }
   9.121 +        onLoad.run();
   9.122 +    }
   9.123 +
   9.124 +    @Override
   9.125 +    public void displayPage(final URL resource, final Runnable onLoad) {
   9.126 +        this.onLoad = onLoad;
   9.127 +        final WebView view = findView(resource);
   9.128 +        this.engine = view.getEngine();
   9.129 +        try {
   9.130 +            if (FXInspect.initialize(engine)) {
   9.131 +                scripts = new ArrayList<String>();
   9.132 +            }
   9.133 +        } catch (Throwable ex) {
   9.134 +            ex.printStackTrace();
   9.135 +        }
   9.136 +
   9.137 +        class Run implements Runnable {
   9.138 +
   9.139 +            @Override
   9.140 +            public void run() {
   9.141 +                if (scripts != null) {
   9.142 +                    view.setContextMenuEnabled(true);
   9.143 +                }
   9.144 +                engine.load(resource.toExternalForm());
   9.145 +            }
   9.146 +        }
   9.147 +        Run run = new Run();
   9.148 +        if (Platform.isFxApplicationThread()) {
   9.149 +            run.run();
   9.150 +        } else {
   9.151 +            Platform.runLater(run);
   9.152 +        }
   9.153 +        waitFinished();
   9.154 +    }
   9.155 +
   9.156 +    protected abstract void waitFinished();
   9.157 +
   9.158 +    protected abstract WebView findView(final URL resource);
   9.159 +
   9.160 +    private static final class JSFn extends Fn {
   9.161 +
   9.162 +        private final JSObject fn;
   9.163 +        private static int call;
   9.164 +        private final int id;
   9.165 +
   9.166 +        public JSFn(AbstractFXPresenter p, JSObject fn, int id) {
   9.167 +            super(p);
   9.168 +            this.fn = fn;
   9.169 +            this.id = id;
   9.170 +        }
   9.171 +
   9.172 +        @Override
   9.173 +        public Object invoke(Object thiz, Object... args) throws Exception {
   9.174 +            try {
   9.175 +                if (LOG.isLoggable(Level.FINE)) {
   9.176 +                    LOG.log(Level.FINE, "calling {0} function #{1}", new Object[]{++call, id});
   9.177 +                }
   9.178 +                List<Object> all = new ArrayList<Object>(args.length + 1);
   9.179 +                all.add(thiz == null ? fn : thiz);
   9.180 +                all.addAll(Arrays.asList(args));
   9.181 +                Object ret = fn.call("call", all.toArray()); // NOI18N
   9.182 +                return ret == fn ? null : ret;
   9.183 +            } catch (Error t) {
   9.184 +                t.printStackTrace();
   9.185 +                throw t;
   9.186 +            } catch (Exception t) {
   9.187 +                t.printStackTrace();
   9.188 +                throw t;
   9.189 +            }
   9.190 +        }
   9.191 +    }
   9.192 +    
   9.193 +}
    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/Dbgr.java	Mon Dec 16 17:16:40 2013 +0100
    10.3 @@ -0,0 +1,87 @@
    10.4 +/**
    10.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    10.6 + *
    10.7 + * Copyright 1997-2010 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.lang.reflect.Method;
   10.49 +import java.util.logging.Level;
   10.50 +import javafx.scene.web.WebEngine;
   10.51 +import javafx.util.Callback;
   10.52 +import static org.netbeans.html.boot.fx.AbstractFXPresenter.LOG;
   10.53 +
   10.54 +/** Debugger bridge to shield us from propriatory impl APIs.
   10.55 + *
   10.56 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   10.57 + */
   10.58 +final class Dbgr {
   10.59 +    final Object dbg;
   10.60 +    final Method sendMsg;
   10.61 +    
   10.62 +    Dbgr(WebEngine eng, Callback<String,Void> callback) {
   10.63 +        Object d;
   10.64 +        Method m;
   10.65 +        try {
   10.66 +            d = eng.getClass().getMethod("impl_getDebugger").invoke(eng); // NOI18N
   10.67 +            Class<?> debugger = eng.getClass().getClassLoader().loadClass("com.sun.javafx.scene.web.Debugger"); // NOI18N
   10.68 +            debugger.getMethod("setEnabled", boolean.class).invoke(d, true); // NOI18N
   10.69 +            debugger.getMethod("setMessageCallback", Callback.class).invoke(d, callback); // NOI18N
   10.70 +            m = debugger.getMethod("sendMessage", String.class); // NOI18N
   10.71 +        } catch (Exception ex) {
   10.72 +            LOG.log(Level.INFO, null, ex);
   10.73 +            d = null;
   10.74 +            m = null;
   10.75 +        }
   10.76 +        dbg = d;
   10.77 +        sendMsg = m;
   10.78 +    }
   10.79 +
   10.80 +    void sendMessage(String msg) {
   10.81 +        try {
   10.82 +            if (dbg != null) {
   10.83 +                sendMsg.invoke(dbg, msg);
   10.84 +            }
   10.85 +        } catch (Exception ex) {
   10.86 +            LOG.log(Level.INFO, null, ex);
   10.87 +        }
   10.88 +    }
   10.89 +    
   10.90 +}
    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/FXBrwsr.java	Mon Dec 16 17:16:40 2013 +0100
    11.3 @@ -0,0 +1,193 @@
    11.4 +/**
    11.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    11.6 + *
    11.7 + * Copyright 1997-2010 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.net.URL;
   11.49 +import java.util.concurrent.CountDownLatch;
   11.50 +import java.util.concurrent.Executors;
   11.51 +import java.util.logging.Level;
   11.52 +import java.util.logging.Logger;
   11.53 +import javafx.application.Application;
   11.54 +import javafx.application.Platform;
   11.55 +import javafx.beans.value.ChangeListener;
   11.56 +import javafx.beans.value.ObservableValue;
   11.57 +import javafx.concurrent.Worker;
   11.58 +import javafx.event.ActionEvent;
   11.59 +import javafx.event.EventHandler;
   11.60 +import javafx.geometry.Insets;
   11.61 +import javafx.geometry.Pos;
   11.62 +import javafx.scene.Scene;
   11.63 +import javafx.scene.control.Button;
   11.64 +import javafx.scene.layout.BorderPane;
   11.65 +import javafx.scene.layout.VBox;
   11.66 +import javafx.scene.text.Text;
   11.67 +import javafx.scene.web.WebEvent;
   11.68 +import javafx.scene.web.WebView;
   11.69 +import javafx.stage.Modality;
   11.70 +import javafx.stage.Stage;
   11.71 +
   11.72 +/** This is an implementation class, use {@link BrowserBuilder} API. Just
   11.73 + * include this JAR on classpath and the {@link BrowserBuilder} API will find
   11.74 + * this implementation automatically.
   11.75 + */
   11.76 +public class FXBrwsr extends Application {
   11.77 +    private static final Logger LOG = Logger.getLogger(FXBrwsr.class.getName());
   11.78 +    private static FXBrwsr INSTANCE;
   11.79 +    private static final CountDownLatch FINISHED = new CountDownLatch(1);
   11.80 +    private BorderPane root;
   11.81 +
   11.82 +    public static synchronized WebView findWebView(final URL url, final FXPresenter onLoad) {
   11.83 +        if (INSTANCE == null) {
   11.84 +            Executors.newFixedThreadPool(1).submit(new Runnable() {
   11.85 +                @Override
   11.86 +                public void run() {
   11.87 +                    try {
   11.88 +                        FXBrwsr.launch(FXBrwsr.class);
   11.89 +                    } catch (Throwable ex) {
   11.90 +                        ex.printStackTrace();
   11.91 +                    } finally {
   11.92 +                        FINISHED.countDown();
   11.93 +                    }
   11.94 +                }
   11.95 +            });
   11.96 +        }
   11.97 +        while (INSTANCE == null) {
   11.98 +            try {
   11.99 +                FXBrwsr.class.wait();
  11.100 +            } catch (InterruptedException ex) {
  11.101 +                // wait more
  11.102 +            }
  11.103 +        }
  11.104 +        if (!Platform.isFxApplicationThread()) {
  11.105 +            final WebView[] arr = {null};
  11.106 +            final CountDownLatch waitForResult = new CountDownLatch(1);
  11.107 +            Platform.runLater(new Runnable() {
  11.108 +                @Override
  11.109 +                public void run() {
  11.110 +                    arr[0] = INSTANCE.newView(url, onLoad);
  11.111 +                    waitForResult.countDown();
  11.112 +                }
  11.113 +            });
  11.114 +            for (;;) {
  11.115 +                try {
  11.116 +                    waitForResult.await();
  11.117 +                    break;
  11.118 +                } catch (InterruptedException ex) {
  11.119 +                    LOG.log(Level.INFO, null, ex);
  11.120 +                }
  11.121 +            }
  11.122 +            return arr[0];
  11.123 +        } else {
  11.124 +            return INSTANCE.newView(url, onLoad);
  11.125 +        }
  11.126 +    }
  11.127 +
  11.128 +    @Override
  11.129 +    public void start(Stage primaryStage) throws Exception {
  11.130 +        synchronized (FXBrwsr.class) {
  11.131 +            INSTANCE = this;
  11.132 +            FXBrwsr.class.notifyAll();
  11.133 +        }
  11.134 +        BorderPane r = new BorderPane();
  11.135 +        Scene scene = new Scene(r, 800, 600);
  11.136 +        primaryStage.setScene(scene);
  11.137 +        primaryStage.show();
  11.138 +        this.root = r;
  11.139 +    }
  11.140 +
  11.141 +    private WebView newView(final URL url, final FXPresenter onLoad) {
  11.142 +        final WebView view = new WebView();
  11.143 +        view.setContextMenuEnabled(false);
  11.144 +        view.getEngine().setOnAlert(new EventHandler<WebEvent<String>>() {
  11.145 +            @Override
  11.146 +            public void handle(WebEvent<String> t) {
  11.147 +                final Stage dialogStage = new Stage();
  11.148 +                dialogStage.initModality(Modality.WINDOW_MODAL);
  11.149 +                dialogStage.setTitle("Warning");
  11.150 +                final Button button = new Button("Close");
  11.151 +                final Text text = new Text(t.getData());
  11.152 +                VBox box = new VBox();
  11.153 +                box.setAlignment(Pos.CENTER);
  11.154 +                box.setSpacing(10);
  11.155 +                box.setPadding(new Insets(10));
  11.156 +                box.getChildren().addAll(text, button);
  11.157 +                dialogStage.setScene(new Scene(box));
  11.158 +                button.setCancelButton(true);
  11.159 +                button.setOnAction(new EventHandler<ActionEvent>() {
  11.160 +                    @Override
  11.161 +                    public void handle(ActionEvent t) {
  11.162 +                        dialogStage.close();
  11.163 +                    }
  11.164 +                });
  11.165 +                dialogStage.centerOnScreen();
  11.166 +                dialogStage.showAndWait();
  11.167 +            }
  11.168 +        });
  11.169 +        root.setCenter(view);
  11.170 +        final Worker<Void> w = view.getEngine().getLoadWorker();
  11.171 +        w.stateProperty().addListener(new ChangeListener<Worker.State>() {
  11.172 +            @Override
  11.173 +            public void changed(ObservableValue<? extends Worker.State> ov, Worker.State t, Worker.State newState) {
  11.174 +                if (newState.equals(Worker.State.SUCCEEDED)) {
  11.175 +                    onLoad.onPageLoad();
  11.176 +                }
  11.177 +                if (newState.equals(Worker.State.FAILED)) {
  11.178 +                    throw new IllegalStateException("Failed to load " + url);
  11.179 +                }
  11.180 +            }
  11.181 +        });
  11.182 +        return view;
  11.183 +    }
  11.184 +
  11.185 +    static void waitFinished() {
  11.186 +        for (;;) {
  11.187 +            try {
  11.188 +                FINISHED.await();
  11.189 +                break;
  11.190 +            } catch (InterruptedException ex) {
  11.191 +                LOG.log(Level.INFO, null, ex);
  11.192 +            }
  11.193 +        }
  11.194 +    }
  11.195 +    
  11.196 +}
    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/FXInspect.java	Mon Dec 16 17:16:40 2013 +0100
    12.3 @@ -0,0 +1,134 @@
    12.4 +/**
    12.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    12.6 + *
    12.7 + * Copyright 1997-2010 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.io.IOException;
   12.49 +import java.io.ObjectInputStream;
   12.50 +import java.io.ObjectOutputStream;
   12.51 +import java.net.InetAddress;
   12.52 +import java.net.Socket;
   12.53 +import java.nio.charset.StandardCharsets;
   12.54 +import java.util.logging.Level;
   12.55 +import java.util.logging.Logger;
   12.56 +import javafx.application.Platform;
   12.57 +import javafx.scene.web.WebEngine;
   12.58 +import javafx.util.Callback;
   12.59 +
   12.60 +/**
   12.61 + *
   12.62 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   12.63 + */
   12.64 +final class FXInspect implements Runnable {
   12.65 +    private static final Logger LOG = Logger.getLogger(FXInspect.class.getName());
   12.66 +    
   12.67 +    
   12.68 +    private final WebEngine engine;
   12.69 +    private final ObjectInputStream input;
   12.70 +    private Dbgr dbg;
   12.71 +    
   12.72 +    private FXInspect(WebEngine engine, int port) throws IOException {
   12.73 +        this.engine = engine;
   12.74 +        
   12.75 +        Socket socket = new Socket(InetAddress.getByName(null), port);
   12.76 +        ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
   12.77 +        this.input = new ObjectInputStream(socket.getInputStream());
   12.78 +        initializeDebugger(output);
   12.79 +    }
   12.80 +    
   12.81 +    static boolean initialize(WebEngine engine) {
   12.82 +        final int inspectPort = Integer.getInteger("netbeans.inspect.port", -1); // NOI18N
   12.83 +        if (inspectPort != -1) {
   12.84 +            try {
   12.85 +                FXInspect inspector = new FXInspect(engine, inspectPort);
   12.86 +                Thread t = new Thread(inspector, "FX<->NetBeans Inspector");
   12.87 +                t.start();
   12.88 +                return true;
   12.89 +            } catch (IOException ex) {
   12.90 +                LOG.log(Level.INFO, "Cannot connect to NetBeans IDE to port " + inspectPort, ex); // NOI18N
   12.91 +            }
   12.92 +        }
   12.93 +        return false;
   12.94 +    }
   12.95 +    
   12.96 +    private void initializeDebugger(final ObjectOutputStream output) {
   12.97 +        Platform.runLater(new Runnable() {
   12.98 +            @Override
   12.99 +            public void run() {
  12.100 +                dbg = new Dbgr(engine, new Callback<String,Void>() {
  12.101 +                    @Override
  12.102 +                    public Void call(String message) {
  12.103 +                        try {
  12.104 +                            byte[] bytes = message.getBytes(StandardCharsets.UTF_8);
  12.105 +                            output.writeInt(bytes.length);
  12.106 +                            output.write(bytes);
  12.107 +                            output.flush();
  12.108 +                        } catch (IOException ioex) {
  12.109 +                            ioex.printStackTrace();
  12.110 +                        }
  12.111 +                        return null;
  12.112 +                    }
  12.113 +                });
  12.114 +            }
  12.115 +        });
  12.116 +    }
  12.117 +
  12.118 +    @Override
  12.119 +    public void run() {
  12.120 +        try {
  12.121 +            while (true) {
  12.122 +                int length = input.readInt();
  12.123 +                byte[] bytes = new byte[length];
  12.124 +                input.readFully(bytes);
  12.125 +                final String message = new String(bytes, StandardCharsets.UTF_8);
  12.126 +                Platform.runLater(new Runnable() {
  12.127 +                    @Override
  12.128 +                    public void run() {
  12.129 +                        dbg.sendMessage(message);
  12.130 +                    }
  12.131 +                });
  12.132 +            }
  12.133 +        } catch (IOException ex) {
  12.134 +            LOG.log(Level.WARNING, null, ex);
  12.135 +        }
  12.136 +    }
  12.137 +}
    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/FXPresenter.java	Mon Dec 16 17:16:40 2013 +0100
    13.3 @@ -0,0 +1,98 @@
    13.4 +/**
    13.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    13.6 + *
    13.7 + * Copyright 1997-2010 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.BufferedReader;
   13.49 +import java.io.File;
   13.50 +import java.io.Reader;
   13.51 +import java.lang.reflect.Method;
   13.52 +import java.net.URL;
   13.53 +import java.net.URLClassLoader;
   13.54 +import java.util.ArrayList;
   13.55 +import java.util.Arrays;
   13.56 +import java.util.List;
   13.57 +import java.util.logging.Level;
   13.58 +import java.util.logging.Logger;
   13.59 +import javafx.application.Platform;
   13.60 +import javafx.scene.web.WebEngine;
   13.61 +import javafx.scene.web.WebView;
   13.62 +import net.java.html.boot.BrowserBuilder;
   13.63 +import netscape.javascript.JSObject;
   13.64 +import org.apidesign.html.boot.spi.Fn;
   13.65 +import org.openide.util.lookup.ServiceProvider;
   13.66 +
   13.67 +/** This is an implementation class, use {@link BrowserBuilder} API. Just
   13.68 + * include this JAR on classpath and the {@link BrowserBuilder} API will find
   13.69 + * this implementation automatically.
   13.70 + *
   13.71 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   13.72 + */
   13.73 +@ServiceProvider(service = Fn.Presenter.class)
   13.74 +public final class FXPresenter extends AbstractFXPresenter {
   13.75 +    static {
   13.76 +        try {
   13.77 +            try {
   13.78 +                Class<?> c = Class.forName("javafx.application.Platform");
   13.79 +                // OK, on classpath
   13.80 +            } catch (ClassNotFoundException classNotFoundException) {
   13.81 +                Method m = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
   13.82 +                m.setAccessible(true);
   13.83 +                File f = new File(System.getProperty("java.home"), "lib/jfxrt.jar");
   13.84 +                if (f.exists()) {
   13.85 +                    URL l = f.toURI().toURL();
   13.86 +                    m.invoke(ClassLoader.getSystemClassLoader(), l);
   13.87 +                }
   13.88 +            }
   13.89 +        } catch (Exception ex) {
   13.90 +            throw new LinkageError("Can't add jfxrt.jar on the classpath", ex);
   13.91 +        }
   13.92 +    }
   13.93 +
   13.94 +    protected void waitFinished() {
   13.95 +        FXBrwsr.waitFinished();
   13.96 +    }
   13.97 +
   13.98 +    protected WebView findView(final URL resource) {
   13.99 +        return FXBrwsr.findWebView(resource, this);
  13.100 +    }
  13.101 +}
    14.1 --- a/boot-fx/src/test/java/net/java/html/boot/fx/FXBrowsersOnResourceTest.java	Mon Dec 16 17:16:02 2013 +0100
    14.2 +++ b/boot-fx/src/test/java/net/java/html/boot/fx/FXBrowsersOnResourceTest.java	Mon Dec 16 17:16:40 2013 +0100
    14.3 @@ -1,22 +1,44 @@
    14.4  /**
    14.5 - * HTML via Java(tm) Language Bindings
    14.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    14.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    14.8   *
    14.9 - * This program is free software: you can redistribute it and/or modify
   14.10 - * it under the terms of the GNU General Public License as published by
   14.11 - * the Free Software Foundation, version 2 of the License.
   14.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   14.13   *
   14.14 - * This program is distributed in the hope that it will be useful,
   14.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14.17 - * GNU General Public License for more details. apidesign.org
   14.18 - * designates this particular file as subject to the
   14.19 - * "Classpath" exception as provided by apidesign.org
   14.20 - * in the License file that accompanied this code.
   14.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   14.22 + * Other names may be trademarks of their respective owners.
   14.23   *
   14.24 - * You should have received a copy of the GNU General Public License
   14.25 - * along with this program. Look for COPYING file in the top folder.
   14.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   14.27 + * The contents of this file are subject to the terms of either the GNU
   14.28 + * General Public License Version 2 only ("GPL") or the Common
   14.29 + * Development and Distribution License("CDDL") (collectively, the
   14.30 + * "License"). You may not use this file except in compliance with the
   14.31 + * License. You can obtain a copy of the License at
   14.32 + * http://www.netbeans.org/cddl-gplv2.html
   14.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   14.34 + * specific language governing permissions and limitations under the
   14.35 + * License.  When distributing the software, include this License Header
   14.36 + * Notice in each file and include the License file at
   14.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   14.38 + * particular file as subject to the "Classpath" exception as provided
   14.39 + * by Oracle in the GPL Version 2 section of the License file that
   14.40 + * accompanied this code. If applicable, add the following below the
   14.41 + * License Header, with the fields enclosed by brackets [] replaced by
   14.42 + * your own identifying information:
   14.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   14.44 + *
   14.45 + * Contributor(s):
   14.46 + *
   14.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   14.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   14.49 + *
   14.50 + * If you wish your version of this file to be governed by only the CDDL
   14.51 + * or only the GPL Version 2, indicate your decision by adding
   14.52 + * "[Contributor] elects to include this software in this distribution
   14.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   14.54 + * single choice of license, a recipient has the option to distribute
   14.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   14.56 + * to extend the choice of license to its licensees as provided above.
   14.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   14.58 + * Version 2 license, then the option applies only if the new code is
   14.59 + * made subject to such option by the copyright holder.
   14.60   */
   14.61  package net.java.html.boot.fx;
   14.62  
   14.63 @@ -73,7 +95,7 @@
   14.64              }
   14.65              
   14.66              private void doTest() throws Throwable {
   14.67 -                URL u = FXBrowsersOnResourceTest.class.getResource("/org/apidesign/html/boot/fx/empty.html");
   14.68 +                URL u = FXBrowsersOnResourceTest.class.getResource("/org/netbeans/html/boot/fx/empty.html");
   14.69                  assertNotNull(u, "URL found");
   14.70                  FXBrowsers.load(App.getV1(), u, OnPages.class, "first");
   14.71                  
   14.72 @@ -109,7 +131,7 @@
   14.73              
   14.74              assertEquals(increment(), 1, "Now it is one");
   14.75              
   14.76 -            URL u = FXBrowsersOnResourceTest.class.getResource("/org/apidesign/html/boot/fx/empty.html");
   14.77 +            URL u = FXBrowsersOnResourceTest.class.getResource("/org/netbeans/html/boot/fx/empty.html");
   14.78              assertNotNull(u, "URL found");
   14.79              FXBrowsers.load(App.getV2(), u, OnPages.class, "second", "Hello");
   14.80              
    15.1 --- a/boot-fx/src/test/java/net/java/html/boot/fx/FXBrowsersTest.java	Mon Dec 16 17:16:02 2013 +0100
    15.2 +++ b/boot-fx/src/test/java/net/java/html/boot/fx/FXBrowsersTest.java	Mon Dec 16 17:16:40 2013 +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 1997-2010 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 = FXBrowsersTest.class.getResource("/org/apidesign/html/boot/fx/empty.html");
   15.68 +                URL u = FXBrowsersTest.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 @@ -108,7 +130,7 @@
   15.73              
   15.74              assertEquals(increment(), 1, "Now it is one");
   15.75              
   15.76 -            URL u = FXBrowsersTest.class.getResource("/org/apidesign/html/boot/fx/empty.html");
   15.77 +            URL u = FXBrowsersTest.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/org/apidesign/html/boot/fx/BootstrapTest.java	Mon Dec 16 17:16:02 2013 +0100
    16.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.3 @@ -1,87 +0,0 @@
    16.4 -/**
    16.5 - * HTML via Java(tm) Language Bindings
    16.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    16.7 - *
    16.8 - * This program is free software: you can redistribute it and/or modify
    16.9 - * it under the terms of the GNU General Public License as published by
   16.10 - * the Free Software Foundation, version 2 of the License.
   16.11 - *
   16.12 - * This program is distributed in the hope that it will be useful,
   16.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   16.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16.15 - * GNU General Public License for more details. apidesign.org
   16.16 - * designates this particular file as subject to the
   16.17 - * "Classpath" exception as provided by apidesign.org
   16.18 - * in the License file that accompanied this code.
   16.19 - *
   16.20 - * You should have received a copy of the GNU General Public License
   16.21 - * along with this program. Look for COPYING file in the top folder.
   16.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   16.23 - */
   16.24 -package org.apidesign.html.boot.fx;
   16.25 -
   16.26 -import java.lang.annotation.Annotation;
   16.27 -import java.lang.reflect.Method;
   16.28 -import java.util.ArrayList;
   16.29 -import java.util.List;
   16.30 -import java.util.concurrent.Executors;
   16.31 -import net.java.html.boot.BrowserBuilder;
   16.32 -import org.apidesign.html.boot.impl.FnContext;
   16.33 -import org.apidesign.html.boot.spi.Fn;
   16.34 -import org.testng.annotations.Factory;
   16.35 -import org.testng.annotations.Test;
   16.36 -
   16.37 -/**
   16.38 - *
   16.39 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   16.40 - */
   16.41 -public class BootstrapTest {
   16.42 -    private static Class<?> browserClass;
   16.43 -    private static Fn.Presenter browserPresenter;
   16.44 -    
   16.45 -    public BootstrapTest() {
   16.46 -    }
   16.47 -
   16.48 -    @Factory public static Object[] compatibilityTests() throws Exception {
   16.49 -        final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(BootstrapTest.class).
   16.50 -            loadPage("empty.html").
   16.51 -            invoke("initialized");
   16.52 -
   16.53 -        Executors.newSingleThreadExecutor().submit(new Runnable() {
   16.54 -            @Override
   16.55 -            public void run() {
   16.56 -                bb.showAndWait();
   16.57 -            }
   16.58 -        });
   16.59 -
   16.60 -        List<Object> res = new ArrayList<Object>();
   16.61 -        Class<? extends Annotation> test = 
   16.62 -            loadClass().getClassLoader().loadClass(Test.class.getName()).
   16.63 -            asSubclass(Annotation.class);
   16.64 -        for (Method m : loadClass().getMethods()) {
   16.65 -            if (m.getAnnotation(test) != null) {
   16.66 -                res.add(new KOFx(browserPresenter, m));
   16.67 -            }
   16.68 -        }
   16.69 -        return res.toArray();
   16.70 -    }
   16.71 -
   16.72 -    static synchronized Class<?> loadClass() throws InterruptedException {
   16.73 -        while (browserClass == null) {
   16.74 -            BootstrapTest.class.wait();
   16.75 -        }
   16.76 -        return browserClass;
   16.77 -    }
   16.78 -    
   16.79 -    public static synchronized void ready(Class<?> browserCls) throws Exception {
   16.80 -        browserClass = browserCls;
   16.81 -        browserPresenter = FnContext.currentPresenter();
   16.82 -        BootstrapTest.class.notifyAll();
   16.83 -    }
   16.84 -    
   16.85 -    public static void initialized() throws Exception {
   16.86 -        Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(BootstrapTest.class.getName());
   16.87 -        Method m = classpathClass.getMethod("ready", Class.class);
   16.88 -        m.invoke(null, FXPresenterTst.class);
   16.89 -    }
   16.90 -}
    17.1 --- a/boot-fx/src/test/java/org/apidesign/html/boot/fx/FXPresenterTst.java	Mon Dec 16 17:16:02 2013 +0100
    17.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.3 @@ -1,49 +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 net.java.html.js.JavaScriptBody;
   17.27 -import static org.testng.Assert.*;
   17.28 -import org.testng.annotations.Test;
   17.29 -
   17.30 -/**
   17.31 - *
   17.32 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   17.33 - */
   17.34 -public class FXPresenterTst {
   17.35 -    @Test public void showClassLoader() {
   17.36 -        R run = new R();
   17.37 -        callback(run);
   17.38 -        assertEquals(run.cnt, 1, "Can call even private implementation classes");
   17.39 -    }
   17.40 -    
   17.41 -    @JavaScriptBody(args = { "r" }, javacall = true, body = "r.@java.lang.Runnable::run()();")
   17.42 -    private static native void callback(Runnable r);
   17.43 -
   17.44 -    private static class R implements Runnable {
   17.45 -        int cnt;
   17.46 -
   17.47 -        @Override
   17.48 -        public void run() {
   17.49 -            cnt++;
   17.50 -        }
   17.51 -    }
   17.52 -}
    18.1 --- a/boot-fx/src/test/java/org/apidesign/html/boot/fx/KOFx.java	Mon Dec 16 17:16:02 2013 +0100
    18.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.3 @@ -1,103 +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 java.lang.reflect.InvocationTargetException;
   18.27 -import java.lang.reflect.Method;
   18.28 -import javafx.application.Platform;
   18.29 -import org.apidesign.html.boot.impl.FnContext;
   18.30 -import org.apidesign.html.boot.spi.Fn;
   18.31 -import org.testng.IHookCallBack;
   18.32 -import org.testng.IHookable;
   18.33 -import org.testng.ITest;
   18.34 -import org.testng.ITestResult;
   18.35 -import org.testng.annotations.Test;
   18.36 -
   18.37 -/**
   18.38 - *
   18.39 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   18.40 - */
   18.41 -public final class KOFx implements ITest, IHookable, Runnable {
   18.42 -    private final Fn.Presenter p;
   18.43 -    private final Method m;
   18.44 -    private Object result;
   18.45 -    private Object inst;
   18.46 -
   18.47 -    KOFx(Fn.Presenter p, Method m) {
   18.48 -        this.p = p;
   18.49 -        this.m = m;
   18.50 -    }
   18.51 -
   18.52 -    @Override
   18.53 -    public String getTestName() {
   18.54 -        return m.getName();
   18.55 -    }
   18.56 -
   18.57 -    @Test
   18.58 -    public synchronized void executeTest() throws Exception {
   18.59 -        if (result == null) {
   18.60 -            Platform.runLater(this);
   18.61 -            wait();
   18.62 -        }
   18.63 -        if (result instanceof Exception) {
   18.64 -            throw (Exception)result;
   18.65 -        }
   18.66 -        if (result instanceof Error) {
   18.67 -            throw (Error)result;
   18.68 -        }
   18.69 -    }
   18.70 -
   18.71 -    @Override
   18.72 -    public synchronized void run() {
   18.73 -        boolean notify = true;
   18.74 -        try {
   18.75 -            FnContext.currentPresenter(p);
   18.76 -            if (inst == null) {
   18.77 -                inst = m.getDeclaringClass().newInstance();
   18.78 -            }
   18.79 -            result = m.invoke(inst);
   18.80 -            if (result == null) {
   18.81 -                result = this;
   18.82 -            }
   18.83 -        } catch (InvocationTargetException ex) {
   18.84 -            Throwable r = ex.getTargetException();
   18.85 -            if (r instanceof InterruptedException) {
   18.86 -                notify = false;
   18.87 -                Platform.runLater(this);
   18.88 -                return;
   18.89 -            }
   18.90 -            result = r;
   18.91 -        } catch (Exception ex) {
   18.92 -            result = ex;
   18.93 -        } finally {
   18.94 -            if (notify) {
   18.95 -                notifyAll();
   18.96 -            }
   18.97 -            FnContext.currentPresenter(null);
   18.98 -        }
   18.99 -    }
  18.100 -
  18.101 -    @Override
  18.102 -    public void run(IHookCallBack ihcb, ITestResult itr) {
  18.103 -        ihcb.runTestMethod(itr);
  18.104 -    }
  18.105 -    
  18.106 -}
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/boot-fx/src/test/java/org/netbeans/html/boot/fx/BootstrapTest.java	Mon Dec 16 17:16:40 2013 +0100
    19.3 @@ -0,0 +1,109 @@
    19.4 +/**
    19.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    19.6 + *
    19.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    19.8 + *
    19.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   19.10 + * Other names may be trademarks of their respective owners.
   19.11 + *
   19.12 + * The contents of this file are subject to the terms of either the GNU
   19.13 + * General Public License Version 2 only ("GPL") or the Common
   19.14 + * Development and Distribution License("CDDL") (collectively, the
   19.15 + * "License"). You may not use this file except in compliance with the
   19.16 + * License. You can obtain a copy of the License at
   19.17 + * http://www.netbeans.org/cddl-gplv2.html
   19.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   19.19 + * specific language governing permissions and limitations under the
   19.20 + * License.  When distributing the software, include this License Header
   19.21 + * Notice in each file and include the License file at
   19.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   19.23 + * particular file as subject to the "Classpath" exception as provided
   19.24 + * by Oracle in the GPL Version 2 section of the License file that
   19.25 + * accompanied this code. If applicable, add the following below the
   19.26 + * License Header, with the fields enclosed by brackets [] replaced by
   19.27 + * your own identifying information:
   19.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   19.29 + *
   19.30 + * Contributor(s):
   19.31 + *
   19.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   19.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   19.34 + *
   19.35 + * If you wish your version of this file to be governed by only the CDDL
   19.36 + * or only the GPL Version 2, indicate your decision by adding
   19.37 + * "[Contributor] elects to include this software in this distribution
   19.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   19.39 + * single choice of license, a recipient has the option to distribute
   19.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   19.41 + * to extend the choice of license to its licensees as provided above.
   19.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   19.43 + * Version 2 license, then the option applies only if the new code is
   19.44 + * made subject to such option by the copyright holder.
   19.45 + */
   19.46 +package org.netbeans.html.boot.fx;
   19.47 +
   19.48 +import java.lang.annotation.Annotation;
   19.49 +import java.lang.reflect.Method;
   19.50 +import java.util.ArrayList;
   19.51 +import java.util.List;
   19.52 +import java.util.concurrent.Executors;
   19.53 +import net.java.html.boot.BrowserBuilder;
   19.54 +import org.netbeans.html.boot.impl.FnContext;
   19.55 +import org.apidesign.html.boot.spi.Fn;
   19.56 +import org.testng.annotations.Factory;
   19.57 +import org.testng.annotations.Test;
   19.58 +
   19.59 +/**
   19.60 + *
   19.61 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   19.62 + */
   19.63 +public class BootstrapTest {
   19.64 +    private static Class<?> browserClass;
   19.65 +    private static Fn.Presenter browserPresenter;
   19.66 +    
   19.67 +    public BootstrapTest() {
   19.68 +    }
   19.69 +
   19.70 +    @Factory public static Object[] compatibilityTests() throws Exception {
   19.71 +        final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(BootstrapTest.class).
   19.72 +            loadPage("empty.html").
   19.73 +            invoke("initialized");
   19.74 +
   19.75 +        Executors.newSingleThreadExecutor().submit(new Runnable() {
   19.76 +            @Override
   19.77 +            public void run() {
   19.78 +                bb.showAndWait();
   19.79 +            }
   19.80 +        });
   19.81 +
   19.82 +        List<Object> res = new ArrayList<Object>();
   19.83 +        Class<? extends Annotation> test = 
   19.84 +            loadClass().getClassLoader().loadClass(Test.class.getName()).
   19.85 +            asSubclass(Annotation.class);
   19.86 +        for (Method m : loadClass().getMethods()) {
   19.87 +            if (m.getAnnotation(test) != null) {
   19.88 +                res.add(new KOFx(browserPresenter, m));
   19.89 +            }
   19.90 +        }
   19.91 +        return res.toArray();
   19.92 +    }
   19.93 +
   19.94 +    static synchronized Class<?> loadClass() throws InterruptedException {
   19.95 +        while (browserClass == null) {
   19.96 +            BootstrapTest.class.wait();
   19.97 +        }
   19.98 +        return browserClass;
   19.99 +    }
  19.100 +    
  19.101 +    public static synchronized void ready(Class<?> browserCls) throws Exception {
  19.102 +        browserClass = browserCls;
  19.103 +        browserPresenter = FnContext.currentPresenter();
  19.104 +        BootstrapTest.class.notifyAll();
  19.105 +    }
  19.106 +    
  19.107 +    public static void initialized() throws Exception {
  19.108 +        Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(BootstrapTest.class.getName());
  19.109 +        Method m = classpathClass.getMethod("ready", Class.class);
  19.110 +        m.invoke(null, FXPresenterTst.class);
  19.111 +    }
  19.112 +}
    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/FXPresenterTst.java	Mon Dec 16 17:16:40 2013 +0100
    20.3 @@ -0,0 +1,71 @@
    20.4 +/**
    20.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    20.6 + *
    20.7 + * Copyright 1997-2010 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 net.java.html.js.JavaScriptBody;
   20.49 +import static org.testng.Assert.*;
   20.50 +import org.testng.annotations.Test;
   20.51 +
   20.52 +/**
   20.53 + *
   20.54 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   20.55 + */
   20.56 +public class FXPresenterTst {
   20.57 +    @Test public void showClassLoader() {
   20.58 +        R run = new R();
   20.59 +        callback(run);
   20.60 +        assertEquals(run.cnt, 1, "Can call even private implementation classes");
   20.61 +    }
   20.62 +    
   20.63 +    @JavaScriptBody(args = { "r" }, javacall = true, body = "r.@java.lang.Runnable::run()();")
   20.64 +    private static native void callback(Runnable r);
   20.65 +
   20.66 +    private static class R implements Runnable {
   20.67 +        int cnt;
   20.68 +
   20.69 +        @Override
   20.70 +        public void run() {
   20.71 +            cnt++;
   20.72 +        }
   20.73 +    }
   20.74 +}
    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/KOFx.java	Mon Dec 16 17:16:40 2013 +0100
    21.3 @@ -0,0 +1,125 @@
    21.4 +/**
    21.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    21.6 + *
    21.7 + * Copyright 1997-2010 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 java.lang.reflect.InvocationTargetException;
   21.49 +import java.lang.reflect.Method;
   21.50 +import javafx.application.Platform;
   21.51 +import org.netbeans.html.boot.impl.FnContext;
   21.52 +import org.apidesign.html.boot.spi.Fn;
   21.53 +import org.testng.IHookCallBack;
   21.54 +import org.testng.IHookable;
   21.55 +import org.testng.ITest;
   21.56 +import org.testng.ITestResult;
   21.57 +import org.testng.annotations.Test;
   21.58 +
   21.59 +/**
   21.60 + *
   21.61 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   21.62 + */
   21.63 +public final class KOFx implements ITest, IHookable, Runnable {
   21.64 +    private final Fn.Presenter p;
   21.65 +    private final Method m;
   21.66 +    private Object result;
   21.67 +    private Object inst;
   21.68 +
   21.69 +    KOFx(Fn.Presenter p, Method m) {
   21.70 +        this.p = p;
   21.71 +        this.m = m;
   21.72 +    }
   21.73 +
   21.74 +    @Override
   21.75 +    public String getTestName() {
   21.76 +        return m.getName();
   21.77 +    }
   21.78 +
   21.79 +    @Test
   21.80 +    public synchronized void executeTest() throws Exception {
   21.81 +        if (result == null) {
   21.82 +            Platform.runLater(this);
   21.83 +            wait();
   21.84 +        }
   21.85 +        if (result instanceof Exception) {
   21.86 +            throw (Exception)result;
   21.87 +        }
   21.88 +        if (result instanceof Error) {
   21.89 +            throw (Error)result;
   21.90 +        }
   21.91 +    }
   21.92 +
   21.93 +    @Override
   21.94 +    public synchronized void run() {
   21.95 +        boolean notify = true;
   21.96 +        try {
   21.97 +            FnContext.currentPresenter(p);
   21.98 +            if (inst == null) {
   21.99 +                inst = m.getDeclaringClass().newInstance();
  21.100 +            }
  21.101 +            result = m.invoke(inst);
  21.102 +            if (result == null) {
  21.103 +                result = this;
  21.104 +            }
  21.105 +        } catch (InvocationTargetException ex) {
  21.106 +            Throwable r = ex.getTargetException();
  21.107 +            if (r instanceof InterruptedException) {
  21.108 +                notify = false;
  21.109 +                Platform.runLater(this);
  21.110 +                return;
  21.111 +            }
  21.112 +            result = r;
  21.113 +        } catch (Exception ex) {
  21.114 +            result = ex;
  21.115 +        } finally {
  21.116 +            if (notify) {
  21.117 +                notifyAll();
  21.118 +            }
  21.119 +            FnContext.currentPresenter(null);
  21.120 +        }
  21.121 +    }
  21.122 +
  21.123 +    @Override
  21.124 +    public void run(IHookCallBack ihcb, ITestResult itr) {
  21.125 +        ihcb.runTestMethod(itr);
  21.126 +    }
  21.127 +    
  21.128 +}
    22.1 --- a/boot-fx/src/test/resources/net/java/html/boot/fx/wnd.js	Mon Dec 16 17:16:02 2013 +0100
    22.2 +++ b/boot-fx/src/test/resources/net/java/html/boot/fx/wnd.js	Mon Dec 16 17:16:40 2013 +0100
    22.3 @@ -1,22 +1,44 @@
    22.4  /*
    22.5 - * HTML via Java(tm) Language Bindings
    22.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    22.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    22.8   *
    22.9 - * This program is free software: you can redistribute it and/or modify
   22.10 - * it under the terms of the GNU General Public License as published by
   22.11 - * the Free Software Foundation, version 2 of the License.
   22.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   22.13   *
   22.14 - * This program is distributed in the hope that it will be useful,
   22.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   22.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   22.17 - * GNU General Public License for more details. apidesign.org
   22.18 - * designates this particular file as subject to the
   22.19 - * "Classpath" exception as provided by apidesign.org
   22.20 - * in the License file that accompanied this code.
   22.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   22.22 + * Other names may be trademarks of their respective owners.
   22.23   *
   22.24 - * You should have received a copy of the GNU General Public License
   22.25 - * along with this program. Look for COPYING file in the top folder.
   22.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   22.27 + * The contents of this file are subject to the terms of either the GNU
   22.28 + * General Public License Version 2 only ("GPL") or the Common
   22.29 + * Development and Distribution License("CDDL") (collectively, the
   22.30 + * "License"). You may not use this file except in compliance with the
   22.31 + * License. You can obtain a copy of the License at
   22.32 + * http://www.netbeans.org/cddl-gplv2.html
   22.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   22.34 + * specific language governing permissions and limitations under the
   22.35 + * License.  When distributing the software, include this License Header
   22.36 + * Notice in each file and include the License file at
   22.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   22.38 + * particular file as subject to the "Classpath" exception as provided
   22.39 + * by Oracle in the GPL Version 2 section of the License file that
   22.40 + * accompanied this code. If applicable, add the following below the
   22.41 + * License Header, with the fields enclosed by brackets [] replaced by
   22.42 + * your own identifying information:
   22.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   22.44 + *
   22.45 + * Contributor(s):
   22.46 + *
   22.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   22.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   22.49 + *
   22.50 + * If you wish your version of this file to be governed by only the CDDL
   22.51 + * or only the GPL Version 2, indicate your decision by adding
   22.52 + * "[Contributor] elects to include this software in this distribution
   22.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   22.54 + * single choice of license, a recipient has the option to distribute
   22.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   22.56 + * to extend the choice of license to its licensees as provided above.
   22.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   22.58 + * Version 2 license, then the option applies only if the new code is
   22.59 + * made subject to such option by the copyright holder.
   22.60   */
   22.61  if (typeof wnd !== 'undefined') {
   22.62      throw 'Window should not be defined yet: ' + wnd;
    23.1 --- a/boot-fx/src/test/resources/org/apidesign/html/boot/fx/empty.html	Mon Dec 16 17:16:02 2013 +0100
    23.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.3 @@ -1,33 +0,0 @@
    23.4 -<!--
    23.5 -
    23.6 -    HTML via Java(tm) Language Bindings
    23.7 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    23.8 -
    23.9 -    This program is free software: you can redistribute it and/or modify
   23.10 -    it under the terms of the GNU General Public License as published by
   23.11 -    the Free Software Foundation, version 2 of the License.
   23.12 -
   23.13 -    This program is distributed in the hope that it will be useful,
   23.14 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   23.15 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   23.16 -    GNU General Public License for more details. apidesign.org
   23.17 -    designates this particular file as subject to the
   23.18 -    "Classpath" exception as provided by apidesign.org
   23.19 -    in the License file that accompanied this code.
   23.20 -
   23.21 -    You should have received a copy of the GNU General Public License
   23.22 -    along with this program. Look for COPYING file in the top folder.
   23.23 -    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   23.24 -
   23.25 --->
   23.26 -<!DOCTYPE html>
   23.27 -<html>
   23.28 -    <head>
   23.29 -        <title>FX Presenter Harness</title>
   23.30 -        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   23.31 -        <meta name="viewport" content="width=device-width">
   23.32 -    </head>
   23.33 -    <body>
   23.34 -        <div>FX Presenter Harness</div>
   23.35 -    </body>
   23.36 -</html>
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/boot-fx/src/test/resources/org/netbeans/html/boot/fx/empty.html	Mon Dec 16 17:16:40 2013 +0100
    24.3 @@ -0,0 +1,55 @@
    24.4 +<!--
    24.5 +
    24.6 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    24.7 +
    24.8 +    Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    24.9 +
   24.10 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   24.11 +    Other names may be trademarks of their respective owners.
   24.12 +
   24.13 +    The contents of this file are subject to the terms of either the GNU
   24.14 +    General Public License Version 2 only ("GPL") or the Common
   24.15 +    Development and Distribution License("CDDL") (collectively, the
   24.16 +    "License"). You may not use this file except in compliance with the
   24.17 +    License. You can obtain a copy of the License at
   24.18 +    http://www.netbeans.org/cddl-gplv2.html
   24.19 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   24.20 +    specific language governing permissions and limitations under the
   24.21 +    License.  When distributing the software, include this License Header
   24.22 +    Notice in each file and include the License file at
   24.23 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   24.24 +    particular file as subject to the "Classpath" exception as provided
   24.25 +    by Oracle in the GPL Version 2 section of the License file that
   24.26 +    accompanied this code. If applicable, add the following below the
   24.27 +    License Header, with the fields enclosed by brackets [] replaced by
   24.28 +    your own identifying information:
   24.29 +    "Portions Copyrighted [year] [name of copyright owner]"
   24.30 +
   24.31 +    Contributor(s):
   24.32 +
   24.33 +    The Original Software is NetBeans. The Initial Developer of the Original
   24.34 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   24.35 +
   24.36 +    If you wish your version of this file to be governed by only the CDDL
   24.37 +    or only the GPL Version 2, indicate your decision by adding
   24.38 +    "[Contributor] elects to include this software in this distribution
   24.39 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
   24.40 +    single choice of license, a recipient has the option to distribute
   24.41 +    your version of this file under either the CDDL, the GPL Version 2 or
   24.42 +    to extend the choice of license to its licensees as provided above.
   24.43 +    However, if you add GPL Version 2 code and therefore, elected the GPL
   24.44 +    Version 2 license, then the option applies only if the new code is
   24.45 +    made subject to such option by the copyright holder.
   24.46 +
   24.47 +-->
   24.48 +<!DOCTYPE html>
   24.49 +<html>
   24.50 +    <head>
   24.51 +        <title>FX Presenter Harness</title>
   24.52 +        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   24.53 +        <meta name="viewport" content="width=device-width">
   24.54 +    </head>
   24.55 +    <body>
   24.56 +        <div>FX Presenter Harness</div>
   24.57 +    </body>
   24.58 +</html>
    25.1 --- a/boot/pom.xml	Mon Dec 16 17:16:02 2013 +0100
    25.2 +++ b/boot/pom.xml	Mon Dec 16 17:16:40 2013 +0100
    25.3 @@ -2,11 +2,11 @@
    25.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">
    25.5    <modelVersion>4.0.0</modelVersion>
    25.6    <parent>
    25.7 -    <groupId>org.apidesign</groupId>
    25.8 -    <artifactId>html</artifactId>
    25.9 +    <groupId>org.netbeans.html</groupId>
   25.10 +    <artifactId>pom</artifactId>
   25.11      <version>0.7-SNAPSHOT</version>
   25.12    </parent>
   25.13 -  <groupId>org.apidesign.html</groupId>
   25.14 +  <groupId>org.netbeans.html</groupId>
   25.15    <artifactId>net.java.html.boot</artifactId>
   25.16    <version>0.7-SNAPSHOT</version>
   25.17    <packaging>bundle</packaging>
   25.18 @@ -23,7 +23,7 @@
   25.19                <artifactId>maven-bundle-plugin</artifactId>
   25.20                <configuration>
   25.21                    <instructions>
   25.22 -                      <Agent-Class>org.apidesign.html.boot.impl.JsAgent</Agent-Class>
   25.23 +                      <Agent-Class>org.netbeans.html.boot.impl.JsAgent</Agent-Class>
   25.24                    </instructions>
   25.25                </configuration>
   25.26            </plugin>
    26.1 --- a/boot/src/main/java/net/java/html/boot/BrowserBuilder.java	Mon Dec 16 17:16:02 2013 +0100
    26.2 +++ b/boot/src/main/java/net/java/html/boot/BrowserBuilder.java	Mon Dec 16 17:16:40 2013 +0100
    26.3 @@ -1,22 +1,44 @@
    26.4  /**
    26.5 - * HTML via Java(tm) Language Bindings
    26.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    26.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    26.8   *
    26.9 - * This program is free software: you can redistribute it and/or modify
   26.10 - * it under the terms of the GNU General Public License as published by
   26.11 - * the Free Software Foundation, version 2 of the License.
   26.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   26.13   *
   26.14 - * This program is distributed in the hope that it will be useful,
   26.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   26.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   26.17 - * GNU General Public License for more details. apidesign.org
   26.18 - * designates this particular file as subject to the
   26.19 - * "Classpath" exception as provided by apidesign.org
   26.20 - * in the License file that accompanied this code.
   26.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   26.22 + * Other names may be trademarks of their respective owners.
   26.23   *
   26.24 - * You should have received a copy of the GNU General Public License
   26.25 - * along with this program. Look for COPYING file in the top folder.
   26.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   26.27 + * The contents of this file are subject to the terms of either the GNU
   26.28 + * General Public License Version 2 only ("GPL") or the Common
   26.29 + * Development and Distribution License("CDDL") (collectively, the
   26.30 + * "License"). You may not use this file except in compliance with the
   26.31 + * License. You can obtain a copy of the License at
   26.32 + * http://www.netbeans.org/cddl-gplv2.html
   26.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   26.34 + * specific language governing permissions and limitations under the
   26.35 + * License.  When distributing the software, include this License Header
   26.36 + * Notice in each file and include the License file at
   26.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   26.38 + * particular file as subject to the "Classpath" exception as provided
   26.39 + * by Oracle in the GPL Version 2 section of the License file that
   26.40 + * accompanied this code. If applicable, add the following below the
   26.41 + * License Header, with the fields enclosed by brackets [] replaced by
   26.42 + * your own identifying information:
   26.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   26.44 + *
   26.45 + * Contributor(s):
   26.46 + *
   26.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   26.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   26.49 + *
   26.50 + * If you wish your version of this file to be governed by only the CDDL
   26.51 + * or only the GPL Version 2, indicate your decision by adding
   26.52 + * "[Contributor] elects to include this software in this distribution
   26.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   26.54 + * single choice of license, a recipient has the option to distribute
   26.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   26.56 + * to extend the choice of license to its licensees as provided above.
   26.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   26.58 + * Version 2 license, then the option applies only if the new code is
   26.59 + * made subject to such option by the copyright holder.
   26.60   */
   26.61  package net.java.html.boot;
   26.62  
   26.63 @@ -32,10 +54,10 @@
   26.64  import java.util.logging.Level;
   26.65  import java.util.logging.Logger;
   26.66  import net.java.html.js.JavaScriptBody;
   26.67 -import org.apidesign.html.boot.impl.FnUtils;
   26.68 +import org.netbeans.html.boot.impl.FnUtils;
   26.69  import org.apidesign.html.boot.spi.Fn;
   26.70 -import org.apidesign.html.boot.impl.FindResources;
   26.71 -import org.apidesign.html.boot.impl.FnContext;
   26.72 +import org.netbeans.html.boot.impl.FindResources;
   26.73 +import org.netbeans.html.boot.impl.FnContext;
   26.74  
   26.75  /** Use this builder to launch your Java/HTML based application. Typical
   26.76   * usage in a main method of your application looks like this: 
   26.77 @@ -60,8 +82,8 @@
   26.78   * also needs an implementation on the classpath of one's application. For example
   26.79   * use: <pre>
   26.80   * &lt;dependency&gt;
   26.81 - *   &lt;groupId&gt;org.apidesign.html&lt;/groupId&gt;
   26.82 - *   &lt;artifactId&gt;boot-fx&lt;/artifactId&gt;
   26.83 + *   &lt;groupId&gt;org.netbeans.html&lt;/groupId&gt;
   26.84 + *   &lt;artifactId&gt;net.java.html.boot.fx&lt;/artifactId&gt;
   26.85   *   &lt;scope&gt;runtime&lt;/scope&gt;
   26.86   * &lt;/dependency&gt;
   26.87   * </pre>
    27.1 --- a/boot/src/main/java/net/java/html/boot/package.html	Mon Dec 16 17:16:02 2013 +0100
    27.2 +++ b/boot/src/main/java/net/java/html/boot/package.html	Mon Dec 16 17:16:40 2013 +0100
    27.3 @@ -1,23 +1,45 @@
    27.4  <!--
    27.5  
    27.6 -    HTML via Java(tm) Language Bindings
    27.7 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    27.8 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    27.9  
   27.10 -    This program is free software: you can redistribute it and/or modify
   27.11 -    it under the terms of the GNU General Public License as published by
   27.12 -    the Free Software Foundation, version 2 of the License.
   27.13 +    Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   27.14  
   27.15 -    This program is distributed in the hope that it will be useful,
   27.16 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   27.17 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   27.18 -    GNU General Public License for more details. apidesign.org
   27.19 -    designates this particular file as subject to the
   27.20 -    "Classpath" exception as provided by apidesign.org
   27.21 -    in the License file that accompanied this code.
   27.22 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   27.23 +    Other names may be trademarks of their respective owners.
   27.24  
   27.25 -    You should have received a copy of the GNU General Public License
   27.26 -    along with this program. Look for COPYING file in the top folder.
   27.27 -    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   27.28 +    The contents of this file are subject to the terms of either the GNU
   27.29 +    General Public License Version 2 only ("GPL") or the Common
   27.30 +    Development and Distribution License("CDDL") (collectively, the
   27.31 +    "License"). You may not use this file except in compliance with the
   27.32 +    License. You can obtain a copy of the License at
   27.33 +    http://www.netbeans.org/cddl-gplv2.html
   27.34 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   27.35 +    specific language governing permissions and limitations under the
   27.36 +    License.  When distributing the software, include this License Header
   27.37 +    Notice in each file and include the License file at
   27.38 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   27.39 +    particular file as subject to the "Classpath" exception as provided
   27.40 +    by Oracle in the GPL Version 2 section of the License file that
   27.41 +    accompanied this code. If applicable, add the following below the
   27.42 +    License Header, with the fields enclosed by brackets [] replaced by
   27.43 +    your own identifying information:
   27.44 +    "Portions Copyrighted [year] [name of copyright owner]"
   27.45 +
   27.46 +    Contributor(s):
   27.47 +
   27.48 +    The Original Software is NetBeans. The Initial Developer of the Original
   27.49 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   27.50 +
   27.51 +    If you wish your version of this file to be governed by only the CDDL
   27.52 +    or only the GPL Version 2, indicate your decision by adding
   27.53 +    "[Contributor] elects to include this software in this distribution
   27.54 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
   27.55 +    single choice of license, a recipient has the option to distribute
   27.56 +    your version of this file under either the CDDL, the GPL Version 2 or
   27.57 +    to extend the choice of license to its licensees as provided above.
   27.58 +    However, if you add GPL Version 2 code and therefore, elected the GPL
   27.59 +    Version 2 license, then the option applies only if the new code is
   27.60 +    made subject to such option by the copyright holder.
   27.61  
   27.62  -->
   27.63  <!DOCTYPE html>
    28.1 --- a/boot/src/main/java/net/java/html/js/JavaScriptBody.java	Mon Dec 16 17:16:02 2013 +0100
    28.2 +++ b/boot/src/main/java/net/java/html/js/JavaScriptBody.java	Mon Dec 16 17:16:40 2013 +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 1997-2010 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.js;
   28.62  
    29.1 --- a/boot/src/main/java/net/java/html/js/JavaScriptResource.java	Mon Dec 16 17:16:02 2013 +0100
    29.2 +++ b/boot/src/main/java/net/java/html/js/JavaScriptResource.java	Mon Dec 16 17:16:40 2013 +0100
    29.3 @@ -1,22 +1,44 @@
    29.4  /**
    29.5 - * HTML via Java(tm) Language Bindings
    29.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    29.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    29.8   *
    29.9 - * This program is free software: you can redistribute it and/or modify
   29.10 - * it under the terms of the GNU General Public License as published by
   29.11 - * the Free Software Foundation, version 2 of the License.
   29.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   29.13   *
   29.14 - * This program is distributed in the hope that it will be useful,
   29.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   29.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   29.17 - * GNU General Public License for more details. apidesign.org
   29.18 - * designates this particular file as subject to the
   29.19 - * "Classpath" exception as provided by apidesign.org
   29.20 - * in the License file that accompanied this code.
   29.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   29.22 + * Other names may be trademarks of their respective owners.
   29.23   *
   29.24 - * You should have received a copy of the GNU General Public License
   29.25 - * along with this program. Look for COPYING file in the top folder.
   29.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   29.27 + * The contents of this file are subject to the terms of either the GNU
   29.28 + * General Public License Version 2 only ("GPL") or the Common
   29.29 + * Development and Distribution License("CDDL") (collectively, the
   29.30 + * "License"). You may not use this file except in compliance with the
   29.31 + * License. You can obtain a copy of the License at
   29.32 + * http://www.netbeans.org/cddl-gplv2.html
   29.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   29.34 + * specific language governing permissions and limitations under the
   29.35 + * License.  When distributing the software, include this License Header
   29.36 + * Notice in each file and include the License file at
   29.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   29.38 + * particular file as subject to the "Classpath" exception as provided
   29.39 + * by Oracle in the GPL Version 2 section of the License file that
   29.40 + * accompanied this code. If applicable, add the following below the
   29.41 + * License Header, with the fields enclosed by brackets [] replaced by
   29.42 + * your own identifying information:
   29.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   29.44 + *
   29.45 + * Contributor(s):
   29.46 + *
   29.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   29.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   29.49 + *
   29.50 + * If you wish your version of this file to be governed by only the CDDL
   29.51 + * or only the GPL Version 2, indicate your decision by adding
   29.52 + * "[Contributor] elects to include this software in this distribution
   29.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   29.54 + * single choice of license, a recipient has the option to distribute
   29.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   29.56 + * to extend the choice of license to its licensees as provided above.
   29.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   29.58 + * Version 2 license, then the option applies only if the new code is
   29.59 + * made subject to such option by the copyright holder.
   29.60   */
   29.61  package net.java.html.js;
   29.62  
    30.1 --- a/boot/src/main/java/net/java/html/js/package.html	Mon Dec 16 17:16:02 2013 +0100
    30.2 +++ b/boot/src/main/java/net/java/html/js/package.html	Mon Dec 16 17:16:40 2013 +0100
    30.3 @@ -1,23 +1,45 @@
    30.4  <!--
    30.5  
    30.6 -    HTML via Java(tm) Language Bindings
    30.7 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    30.8 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    30.9  
   30.10 -    This program is free software: you can redistribute it and/or modify
   30.11 -    it under the terms of the GNU General Public License as published by
   30.12 -    the Free Software Foundation, version 2 of the License.
   30.13 +    Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   30.14  
   30.15 -    This program is distributed in the hope that it will be useful,
   30.16 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   30.17 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   30.18 -    GNU General Public License for more details. apidesign.org
   30.19 -    designates this particular file as subject to the
   30.20 -    "Classpath" exception as provided by apidesign.org
   30.21 -    in the License file that accompanied this code.
   30.22 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   30.23 +    Other names may be trademarks of their respective owners.
   30.24  
   30.25 -    You should have received a copy of the GNU General Public License
   30.26 -    along with this program. Look for COPYING file in the top folder.
   30.27 -    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   30.28 +    The contents of this file are subject to the terms of either the GNU
   30.29 +    General Public License Version 2 only ("GPL") or the Common
   30.30 +    Development and Distribution License("CDDL") (collectively, the
   30.31 +    "License"). You may not use this file except in compliance with the
   30.32 +    License. You can obtain a copy of the License at
   30.33 +    http://www.netbeans.org/cddl-gplv2.html
   30.34 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   30.35 +    specific language governing permissions and limitations under the
   30.36 +    License.  When distributing the software, include this License Header
   30.37 +    Notice in each file and include the License file at
   30.38 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   30.39 +    particular file as subject to the "Classpath" exception as provided
   30.40 +    by Oracle in the GPL Version 2 section of the License file that
   30.41 +    accompanied this code. If applicable, add the following below the
   30.42 +    License Header, with the fields enclosed by brackets [] replaced by
   30.43 +    your own identifying information:
   30.44 +    "Portions Copyrighted [year] [name of copyright owner]"
   30.45 +
   30.46 +    Contributor(s):
   30.47 +
   30.48 +    The Original Software is NetBeans. The Initial Developer of the Original
   30.49 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   30.50 +
   30.51 +    If you wish your version of this file to be governed by only the CDDL
   30.52 +    or only the GPL Version 2, indicate your decision by adding
   30.53 +    "[Contributor] elects to include this software in this distribution
   30.54 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
   30.55 +    single choice of license, a recipient has the option to distribute
   30.56 +    your version of this file under either the CDDL, the GPL Version 2 or
   30.57 +    to extend the choice of license to its licensees as provided above.
   30.58 +    However, if you add GPL Version 2 code and therefore, elected the GPL
   30.59 +    Version 2 license, then the option applies only if the new code is
   30.60 +    made subject to such option by the copyright holder.
   30.61  
   30.62  -->
   30.63  <!DOCTYPE html>
    31.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/FindResources.java	Mon Dec 16 17:16:02 2013 +0100
    31.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.3 @@ -1,34 +0,0 @@
    31.4 -/**
    31.5 - * HTML via Java(tm) Language Bindings
    31.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    31.7 - *
    31.8 - * This program is free software: you can redistribute it and/or modify
    31.9 - * it under the terms of the GNU General Public License as published by
   31.10 - * the Free Software Foundation, version 2 of the License.
   31.11 - *
   31.12 - * This program is distributed in the hope that it will be useful,
   31.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   31.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   31.15 - * GNU General Public License for more details. apidesign.org
   31.16 - * designates this particular file as subject to the
   31.17 - * "Classpath" exception as provided by apidesign.org
   31.18 - * in the License file that accompanied this code.
   31.19 - *
   31.20 - * You should have received a copy of the GNU General Public License
   31.21 - * along with this program. Look for COPYING file in the top folder.
   31.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   31.23 - */
   31.24 -package org.apidesign.html.boot.impl;
   31.25 -
   31.26 -import java.net.URL;
   31.27 -import java.util.Collection;
   31.28 -
   31.29 -/**
   31.30 - *
   31.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   31.32 - */
   31.33 -public interface FindResources {
   31.34 -
   31.35 -    public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough);
   31.36 -    
   31.37 -}
    32.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/FnContext.java	Mon Dec 16 17:16:02 2013 +0100
    32.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.3 @@ -1,76 +0,0 @@
    32.4 -/**
    32.5 - * HTML via Java(tm) Language Bindings
    32.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    32.7 - *
    32.8 - * This program is free software: you can redistribute it and/or modify
    32.9 - * it under the terms of the GNU General Public License as published by
   32.10 - * the Free Software Foundation, version 2 of the License.
   32.11 - *
   32.12 - * This program is distributed in the hope that it will be useful,
   32.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   32.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   32.15 - * GNU General Public License for more details. apidesign.org
   32.16 - * designates this particular file as subject to the
   32.17 - * "Classpath" exception as provided by apidesign.org
   32.18 - * in the License file that accompanied this code.
   32.19 - *
   32.20 - * You should have received a copy of the GNU General Public License
   32.21 - * along with this program. Look for COPYING file in the top folder.
   32.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   32.23 - */
   32.24 -package org.apidesign.html.boot.impl;
   32.25 -
   32.26 -import java.io.Closeable;
   32.27 -import java.io.IOException;
   32.28 -import java.util.logging.Logger;
   32.29 -import org.apidesign.html.boot.spi.Fn;
   32.30 -
   32.31 -/**
   32.32 - *
   32.33 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   32.34 - */
   32.35 -public final class FnContext implements Closeable {
   32.36 -    private static final Logger LOG = Logger.getLogger(FnContext.class.getName());
   32.37 -
   32.38 -    private Object prev;
   32.39 -    private FnContext(Fn.Presenter p) {
   32.40 -        this.prev = p;
   32.41 -    }
   32.42 -
   32.43 -    @Override
   32.44 -    public void close() throws IOException {
   32.45 -        if (prev != this) {
   32.46 -            currentPresenter((Fn.Presenter)prev);
   32.47 -            prev = this;
   32.48 -        }
   32.49 -    }
   32.50 -/*
   32.51 -    @Override
   32.52 -    protected void finalize() throws Throwable {
   32.53 -        if (prev != null) {
   32.54 -            LOG.warning("Unclosed context!");
   32.55 -        }
   32.56 -    }
   32.57 -*/
   32.58 -    public static Closeable activate(Fn.Presenter newP) {
   32.59 -        return new FnContext(currentPresenter(newP));
   32.60 -    }
   32.61 -    
   32.62 -    
   32.63 -    private static final ThreadLocal<Fn.Presenter> CURRENT = new ThreadLocal<Fn.Presenter>();
   32.64 -
   32.65 -    public static Fn.Presenter currentPresenter(Fn.Presenter p) {
   32.66 -        Fn.Presenter prev = CURRENT.get();
   32.67 -        CURRENT.set(p);
   32.68 -        return prev;
   32.69 -    }
   32.70 -
   32.71 -    public static Fn.Presenter currentPresenter() {
   32.72 -        Fn.Presenter p = CURRENT.get();
   32.73 -        if (p == null) {
   32.74 -            throw new IllegalStateException("No current WebView context around!");
   32.75 -        }
   32.76 -        return p;
   32.77 -    }
   32.78 -    
   32.79 -}
    33.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/FnUtils.java	Mon Dec 16 17:16:02 2013 +0100
    33.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.3 @@ -1,575 +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.io.Closeable;
   33.27 -import java.io.InputStream;
   33.28 -import java.io.InputStreamReader;
   33.29 -import java.io.Reader;
   33.30 -import java.net.URL;
   33.31 -import java.util.ArrayList;
   33.32 -import java.util.Collections;
   33.33 -import java.util.Enumeration;
   33.34 -import java.util.List;
   33.35 -import java.util.concurrent.Callable;
   33.36 -import org.apidesign.html.boot.spi.Fn;
   33.37 -import org.objectweb.asm.AnnotationVisitor;
   33.38 -import org.objectweb.asm.ClassReader;
   33.39 -import org.objectweb.asm.ClassVisitor;
   33.40 -import org.objectweb.asm.ClassWriter;
   33.41 -import org.objectweb.asm.Label;
   33.42 -import org.objectweb.asm.MethodVisitor;
   33.43 -import org.objectweb.asm.Opcodes;
   33.44 -import org.objectweb.asm.Type;
   33.45 -import org.objectweb.asm.signature.SignatureReader;
   33.46 -import org.objectweb.asm.signature.SignatureVisitor;
   33.47 -import org.objectweb.asm.signature.SignatureWriter;
   33.48 -
   33.49 -/**
   33.50 - *
   33.51 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   33.52 - */
   33.53 -public final class FnUtils implements Fn.Presenter {
   33.54 -    
   33.55 -    private FnUtils() {
   33.56 -    }
   33.57 -    
   33.58 -    public static boolean isJavaScriptCapable(ClassLoader l) {
   33.59 -        if (l instanceof JsClassLoader) {
   33.60 -            return true;
   33.61 -        }
   33.62 -        Class<?> clazz;
   33.63 -        try (Closeable c = Fn.activate(new FnUtils())) {
   33.64 -            clazz = Class.forName(Test.class.getName(), true, l);
   33.65 -            final Object is = ((Callable<?>)clazz.newInstance()).call();
   33.66 -            return Boolean.TRUE.equals(is);
   33.67 -        } catch (Exception ex) {
   33.68 -            return false;
   33.69 -        }
   33.70 -    }
   33.71 -    
   33.72 -    public static boolean isValid(Fn fn) {
   33.73 -        return fn != null && fn.isValid();
   33.74 -    }
   33.75 -
   33.76 -    public static ClassLoader newLoader(final FindResources f, final Fn.Presenter d, ClassLoader parent) {
   33.77 -        return new JsClassLoader(parent) {
   33.78 -            @Override
   33.79 -            protected URL findResource(String name) {
   33.80 -                List<URL> l = res(name, true);
   33.81 -                return l.isEmpty() ? null : l.get(0);
   33.82 -            }
   33.83 -            
   33.84 -            @Override
   33.85 -            protected Enumeration<URL> findResources(String name) {
   33.86 -                return Collections.enumeration(res(name, false));
   33.87 -            }
   33.88 -            
   33.89 -            private List<URL> res(String name, boolean oneIsEnough) {
   33.90 -                List<URL> l = new ArrayList<URL>();
   33.91 -                f.findResources(name, l, oneIsEnough);
   33.92 -                return l;
   33.93 -            }
   33.94 -            
   33.95 -            @Override
   33.96 -            protected Fn defineFn(String code, String... names) {
   33.97 -                return d.defineFn(code, names);
   33.98 -            }
   33.99 -
  33.100 -            @Override
  33.101 -            protected void loadScript(Reader code) throws Exception {
  33.102 -                d.loadScript(code);
  33.103 -            }
  33.104 -        };
  33.105 -    }
  33.106 -
  33.107 -    static String callback(final String body) {
  33.108 -        return new JsCallback() {
  33.109 -            @Override
  33.110 -            protected CharSequence callMethod(
  33.111 -                String ident, String fqn, String method, String params
  33.112 -            ) {
  33.113 -                StringBuilder sb = new StringBuilder();
  33.114 -                sb.append("vm.").append(mangle(fqn, method, params));
  33.115 -                sb.append("(");
  33.116 -                if (ident != null) {
  33.117 -                    sb.append(ident);
  33.118 -                }
  33.119 -                return sb;
  33.120 -            }
  33.121 -
  33.122 -        }.parse(body);
  33.123 -    }
  33.124 -
  33.125 -    static void loadScript(ClassLoader jcl, String resource) {
  33.126 -        final InputStream script = jcl.getResourceAsStream(resource);
  33.127 -        if (script == null) {
  33.128 -            throw new NullPointerException("Can't find " + resource);
  33.129 -        }
  33.130 -        try {
  33.131 -            Reader isr = null;
  33.132 -            try {
  33.133 -                isr = new InputStreamReader(script, "UTF-8");
  33.134 -                FnContext.currentPresenter().loadScript(isr);
  33.135 -            } finally {
  33.136 -                if (isr != null) {
  33.137 -                    isr.close();
  33.138 -                }
  33.139 -            }
  33.140 -        } catch (Exception ex) {
  33.141 -            throw new IllegalStateException("Can't execute " + resource, ex);
  33.142 -        } 
  33.143 -    }
  33.144 -
  33.145 -    @Override
  33.146 -    public Fn defineFn(String code, String... names) {
  33.147 -        return new TrueFn();
  33.148 -    }
  33.149 -
  33.150 -    @Override
  33.151 -    public void displayPage(URL page, Runnable onPageLoad) {
  33.152 -    }
  33.153 -
  33.154 -    @Override
  33.155 -    public void loadScript(Reader code) throws Exception {
  33.156 -    }
  33.157 -    
  33.158 -    private static final class FindInClass extends ClassVisitor {
  33.159 -        private String name;
  33.160 -        private int found;
  33.161 -        private ClassLoader loader;
  33.162 -        private String resource;
  33.163 -
  33.164 -        public FindInClass(ClassLoader l, ClassVisitor cv) {
  33.165 -            super(Opcodes.ASM4, cv);
  33.166 -            this.loader = l;
  33.167 -        }
  33.168 -
  33.169 -        @Override
  33.170 -        public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
  33.171 -            this.name = name;
  33.172 -            super.visit(version, access, name, signature, superName, interfaces);
  33.173 -        }
  33.174 -
  33.175 -        @Override
  33.176 -        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
  33.177 -            if ("Lnet/java/html/js/JavaScriptResource;".equals(desc)) {
  33.178 -                return new LoadResource();
  33.179 -            }
  33.180 -            return super.visitAnnotation(desc, visible);
  33.181 -        }
  33.182 -
  33.183 -        @Override
  33.184 -        public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
  33.185 -            return new FindInMethod(access, name, desc,
  33.186 -                    super.visitMethod(access & (~Opcodes.ACC_NATIVE), name, desc, signature, exceptions)
  33.187 -            );
  33.188 -        }
  33.189 -
  33.190 -        private final class FindInMethod extends MethodVisitor {
  33.191 -
  33.192 -            private final String name;
  33.193 -            private final String desc;
  33.194 -            private final int access;
  33.195 -            private List<String> args;
  33.196 -            private String body;
  33.197 -            private boolean bodyGenerated;
  33.198 -
  33.199 -            public FindInMethod(int access, String name, String desc, MethodVisitor mv) {
  33.200 -                super(Opcodes.ASM4, mv);
  33.201 -                this.access = access;
  33.202 -                this.name = name;
  33.203 -                this.desc = desc;
  33.204 -            }
  33.205 -
  33.206 -            @Override
  33.207 -            public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
  33.208 -                if ("Lnet/java/html/js/JavaScriptBody;".equals(desc) // NOI18N
  33.209 -                        || "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;".equals(desc) // NOI18N
  33.210 -                        ) {
  33.211 -                    found++;
  33.212 -                    return new FindInAnno();
  33.213 -                }
  33.214 -                return super.visitAnnotation(desc, visible);
  33.215 -            }
  33.216 -
  33.217 -            private void generateJSBody(List<String> args, String body) {
  33.218 -                this.args = args;
  33.219 -                this.body = body;
  33.220 -            }
  33.221 -
  33.222 -            @Override
  33.223 -            public void visitCode() {
  33.224 -                if (body == null) {
  33.225 -                    return;
  33.226 -                }
  33.227 -                generateBody();
  33.228 -            }
  33.229 -
  33.230 -            private boolean generateBody() {
  33.231 -                if (bodyGenerated) {
  33.232 -                    return false;
  33.233 -                }
  33.234 -                bodyGenerated = true;
  33.235 -
  33.236 -                super.visitFieldInsn(
  33.237 -                        Opcodes.GETSTATIC, FindInClass.this.name,
  33.238 -                        "$$fn$$" + name + "_" + found,
  33.239 -                        "Lorg/apidesign/html/boot/spi/Fn;"
  33.240 -                );
  33.241 -                super.visitInsn(Opcodes.DUP);
  33.242 -                super.visitMethodInsn(
  33.243 -                        Opcodes.INVOKESTATIC,
  33.244 -                        "org/apidesign/html/boot/spi/Fn", "isValid",
  33.245 -                        "(Lorg/apidesign/html/boot/spi/Fn;)Z"
  33.246 -                );
  33.247 -                Label ifNotNull = new Label();
  33.248 -                super.visitJumpInsn(Opcodes.IFNE, ifNotNull);
  33.249 -
  33.250 -                // init Fn
  33.251 -                super.visitInsn(Opcodes.POP);
  33.252 -                super.visitLdcInsn(Type.getObjectType(FindInClass.this.name));
  33.253 -                super.visitLdcInsn(body);
  33.254 -                super.visitIntInsn(Opcodes.SIPUSH, args.size());
  33.255 -                super.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/String");
  33.256 -                boolean needsVM = false;
  33.257 -                for (int i = 0; i < args.size(); i++) {
  33.258 -                    assert !needsVM;
  33.259 -                    String argName = args.get(i);
  33.260 -                    needsVM = "vm".equals(argName);
  33.261 -                    super.visitInsn(Opcodes.DUP);
  33.262 -                    super.visitIntInsn(Opcodes.BIPUSH, i);
  33.263 -                    super.visitLdcInsn(argName);
  33.264 -                    super.visitInsn(Opcodes.AASTORE);
  33.265 -                }
  33.266 -                super.visitMethodInsn(Opcodes.INVOKESTATIC,
  33.267 -                        "org/apidesign/html/boot/spi/Fn", "define",
  33.268 -                        "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/String;)Lorg/apidesign/html/boot/spi/Fn;"
  33.269 -                );
  33.270 -                if (resource != null) {
  33.271 -                    super.visitLdcInsn(Type.getObjectType(FindInClass.this.name));
  33.272 -                    super.visitLdcInsn(resource);
  33.273 -                    super.visitMethodInsn(Opcodes.INVOKESTATIC,
  33.274 -                            "org/apidesign/html/boot/spi/Fn", "preload",
  33.275 -                            "(Lorg/apidesign/html/boot/spi/Fn;Ljava/lang/Class;Ljava/lang/String;)Lorg/apidesign/html/boot/spi/Fn;"
  33.276 -                    );
  33.277 -                }
  33.278 -                super.visitInsn(Opcodes.DUP);
  33.279 -                super.visitFieldInsn(
  33.280 -                        Opcodes.PUTSTATIC, FindInClass.this.name,
  33.281 -                        "$$fn$$" + name + "_" + found,
  33.282 -                        "Lorg/apidesign/html/boot/spi/Fn;"
  33.283 -                );
  33.284 -                // end of Fn init
  33.285 -
  33.286 -                super.visitLabel(ifNotNull);
  33.287 -
  33.288 -                final int offset;
  33.289 -                if ((access & Opcodes.ACC_STATIC) == 0) {
  33.290 -                    offset = 1;
  33.291 -                    super.visitIntInsn(Opcodes.ALOAD, 0);
  33.292 -                } else {
  33.293 -                    offset = 0;
  33.294 -                    super.visitInsn(Opcodes.ACONST_NULL);
  33.295 -                }
  33.296 -
  33.297 -                super.visitIntInsn(Opcodes.SIPUSH, args.size());
  33.298 -                super.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
  33.299 -
  33.300 -                class SV extends SignatureVisitor {
  33.301 -
  33.302 -                    private boolean nowReturn;
  33.303 -                    private Type returnType;
  33.304 -                    private int index;
  33.305 -                    private int loadIndex = offset;
  33.306 -
  33.307 -                    public SV() {
  33.308 -                        super(Opcodes.ASM4);
  33.309 -                    }
  33.310 -
  33.311 -                    @Override
  33.312 -                    public void visitBaseType(char descriptor) {
  33.313 -                        final Type t = Type.getType("" + descriptor);
  33.314 -                        if (nowReturn) {
  33.315 -                            returnType = t;
  33.316 -                            return;
  33.317 -                        }
  33.318 -                        FindInMethod.super.visitInsn(Opcodes.DUP);
  33.319 -                        FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, index++);
  33.320 -                        FindInMethod.super.visitVarInsn(t.getOpcode(Opcodes.ILOAD), loadIndex++);
  33.321 -                        String factory;
  33.322 -                        switch (descriptor) {
  33.323 -                            case 'I':
  33.324 -                                factory = "java/lang/Integer";
  33.325 -                                break;
  33.326 -                            case 'J':
  33.327 -                                factory = "java/lang/Long";
  33.328 -                                loadIndex++;
  33.329 -                                break;
  33.330 -                            case 'S':
  33.331 -                                factory = "java/lang/Short";
  33.332 -                                break;
  33.333 -                            case 'F':
  33.334 -                                factory = "java/lang/Float";
  33.335 -                                break;
  33.336 -                            case 'D':
  33.337 -                                factory = "java/lang/Double";
  33.338 -                                loadIndex++;
  33.339 -                                break;
  33.340 -                            case 'Z':
  33.341 -                                factory = "java/lang/Boolean";
  33.342 -                                break;
  33.343 -                            case 'C':
  33.344 -                                factory = "java/lang/Character";
  33.345 -                                break;
  33.346 -                            case 'B':
  33.347 -                                factory = "java/lang/Byte";
  33.348 -                                break;
  33.349 -                            default:
  33.350 -                                throw new IllegalStateException(t.toString());
  33.351 -                        }
  33.352 -                        FindInMethod.super.visitMethodInsn(Opcodes.INVOKESTATIC,
  33.353 -                                factory, "valueOf", "(" + descriptor + ")L" + factory + ";"
  33.354 -                        );
  33.355 -                        FindInMethod.super.visitInsn(Opcodes.AASTORE);
  33.356 -                    }
  33.357 -
  33.358 -                    @Override
  33.359 -                    public SignatureVisitor visitArrayType() {
  33.360 -                        if (nowReturn) {
  33.361 -                            throw new IllegalStateException("Not supported yet");
  33.362 -                        }
  33.363 -                        loadObject();
  33.364 -                        return new SignatureWriter();
  33.365 -                    }
  33.366 -
  33.367 -                    @Override
  33.368 -                    public void visitClassType(String name) {
  33.369 -                        if (nowReturn) {
  33.370 -                            returnType = Type.getObjectType(name);
  33.371 -                            return;
  33.372 -                        }
  33.373 -                        loadObject();
  33.374 -                    }
  33.375 -
  33.376 -                    @Override
  33.377 -                    public SignatureVisitor visitReturnType() {
  33.378 -                        nowReturn = true;
  33.379 -                        return this;
  33.380 -                    }
  33.381 -
  33.382 -                    private void loadObject() {
  33.383 -                        FindInMethod.super.visitInsn(Opcodes.DUP);
  33.384 -                        FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, index++);
  33.385 -                        FindInMethod.super.visitVarInsn(Opcodes.ALOAD, loadIndex++);
  33.386 -                        FindInMethod.super.visitInsn(Opcodes.AASTORE);
  33.387 -                    }
  33.388 -
  33.389 -                }
  33.390 -                SV sv = new SV();
  33.391 -                SignatureReader sr = new SignatureReader(desc);
  33.392 -                sr.accept(sv);
  33.393 -
  33.394 -                if (needsVM) {
  33.395 -                    FindInMethod.super.visitInsn(Opcodes.DUP);
  33.396 -                    FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, sv.index);
  33.397 -                    int lastSlash = FindInClass.this.name.lastIndexOf('/');
  33.398 -                    String jsCallbacks = FindInClass.this.name.substring(0, lastSlash + 1) + "$JsCallbacks$";
  33.399 -                    FindInMethod.super.visitFieldInsn(Opcodes.GETSTATIC, jsCallbacks, "VM", "L" + jsCallbacks + ";");
  33.400 -                    FindInMethod.super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, jsCallbacks, "current", "()L" + jsCallbacks + ";");
  33.401 -                    FindInMethod.super.visitInsn(Opcodes.AASTORE);
  33.402 -                }
  33.403 -
  33.404 -                super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
  33.405 -                        "org/apidesign/html/boot/spi/Fn", "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"
  33.406 -                );
  33.407 -                switch (sv.returnType.getSort()) {
  33.408 -                    case Type.VOID:
  33.409 -                        super.visitInsn(Opcodes.RETURN);
  33.410 -                        break;
  33.411 -                    case Type.ARRAY:
  33.412 -                    case Type.OBJECT:
  33.413 -                        super.visitTypeInsn(Opcodes.CHECKCAST, sv.returnType.getInternalName());
  33.414 -                        super.visitInsn(Opcodes.ARETURN);
  33.415 -                        break;
  33.416 -                    case Type.BOOLEAN:
  33.417 -                        super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Boolean");
  33.418 -                        super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
  33.419 -                                "java/lang/Boolean", "booleanValue", "()Z"
  33.420 -                        );
  33.421 -                        super.visitInsn(Opcodes.IRETURN);
  33.422 -                        break;
  33.423 -                    default:
  33.424 -                        super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Number");
  33.425 -                        super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
  33.426 -                                "java/lang/Number", sv.returnType.getClassName() + "Value", "()" + sv.returnType.getDescriptor()
  33.427 -                        );
  33.428 -                        super.visitInsn(sv.returnType.getOpcode(Opcodes.IRETURN));
  33.429 -                }
  33.430 -                return true;
  33.431 -            }
  33.432 -
  33.433 -            @Override
  33.434 -            public void visitEnd() {
  33.435 -                super.visitEnd();
  33.436 -                if (body != null) {
  33.437 -                    if (generateBody()) {
  33.438 -                        // native method
  33.439 -                        super.visitMaxs(1, 0);
  33.440 -                    }
  33.441 -                    FindInClass.this.visitField(
  33.442 -                            Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
  33.443 -                            "$$fn$$" + name + "_" + found,
  33.444 -                            "Lorg/apidesign/html/boot/spi/Fn;",
  33.445 -                            null, null
  33.446 -                    );
  33.447 -                }
  33.448 -            }
  33.449 -
  33.450 -            private final class FindInAnno extends AnnotationVisitor {
  33.451 -
  33.452 -                private List<String> args = new ArrayList<String>();
  33.453 -                private String body;
  33.454 -                private boolean javacall = false;
  33.455 -
  33.456 -                public FindInAnno() {
  33.457 -                    super(Opcodes.ASM4);
  33.458 -                }
  33.459 -
  33.460 -                @Override
  33.461 -                public void visit(String name, Object value) {
  33.462 -                    if (name == null) {
  33.463 -                        args.add((String) value);
  33.464 -                        return;
  33.465 -                    }
  33.466 -                    if (name.equals("javacall")) { // NOI18N
  33.467 -                        javacall = (Boolean) value;
  33.468 -                        return;
  33.469 -                    }
  33.470 -                    assert name.equals("body");
  33.471 -                    body = (String) value;
  33.472 -                }
  33.473 -
  33.474 -                @Override
  33.475 -                public AnnotationVisitor visitArray(String name) {
  33.476 -                    return this;
  33.477 -                }
  33.478 -
  33.479 -                @Override
  33.480 -                public void visitEnd() {
  33.481 -                    if (body != null) {
  33.482 -                        if (javacall) {
  33.483 -                            body = callback(body);
  33.484 -                            args.add("vm");
  33.485 -                        }
  33.486 -                        generateJSBody(args, body);
  33.487 -                    }
  33.488 -                }
  33.489 -            }
  33.490 -        }
  33.491 -
  33.492 -        private final class LoadResource extends AnnotationVisitor {
  33.493 -
  33.494 -            public LoadResource() {
  33.495 -                super(Opcodes.ASM4);
  33.496 -            }
  33.497 -
  33.498 -            @Override
  33.499 -            public void visit(String attrName, Object value) {
  33.500 -                String relPath = (String) value;
  33.501 -                if (relPath.startsWith("/")) {
  33.502 -                    resource = relPath;
  33.503 -                } else {
  33.504 -                    int last = name.lastIndexOf('/');
  33.505 -                    String fullPath = name.substring(0, last + 1) + relPath;
  33.506 -                    resource = fullPath;
  33.507 -                }
  33.508 -            }
  33.509 -        }
  33.510 -    }
  33.511 -
  33.512 -    private static class ClassWriterEx extends ClassWriter {
  33.513 -
  33.514 -        private ClassLoader loader;
  33.515 -
  33.516 -        public ClassWriterEx(ClassLoader l, ClassReader classReader, int flags) {
  33.517 -            super(classReader, flags);
  33.518 -            this.loader = l;
  33.519 -        }
  33.520 -
  33.521 -        @Override
  33.522 -        protected String getCommonSuperClass(final String type1, final String type2) {
  33.523 -            Class<?> c, d;
  33.524 -            try {
  33.525 -                c = Class.forName(type1.replace('/', '.'), false, loader);
  33.526 -                d = Class.forName(type2.replace('/', '.'), false, loader);
  33.527 -            } catch (Exception e) {
  33.528 -                throw new RuntimeException(e.toString());
  33.529 -            }
  33.530 -            if (c.isAssignableFrom(d)) {
  33.531 -                return type1;
  33.532 -            }
  33.533 -            if (d.isAssignableFrom(c)) {
  33.534 -                return type2;
  33.535 -            }
  33.536 -            if (c.isInterface() || d.isInterface()) {
  33.537 -                return "java/lang/Object";
  33.538 -            } else {
  33.539 -                do {
  33.540 -                    c = c.getSuperclass();
  33.541 -                } while (!c.isAssignableFrom(d));
  33.542 -                return c.getName().replace('.', '/');
  33.543 -            }
  33.544 -        }
  33.545 -    }
  33.546 -
  33.547 -    static byte[] transform(ClassLoader loader, byte[] arr) {
  33.548 -        ClassReader cr = new ClassReader(arr) {
  33.549 -            // to allow us to compile with -profile compact1 on 
  33.550 -            // JDK8 while processing the class as JDK7, the highest
  33.551 -            // class format asm 4.1 understands to
  33.552 -            @Override
  33.553 -            public short readShort(int index) {
  33.554 -                short s = super.readShort(index);
  33.555 -                if (index == 6 && s > Opcodes.V1_7) {
  33.556 -                    return Opcodes.V1_7;
  33.557 -                }
  33.558 -                return s;
  33.559 -            }
  33.560 -        };
  33.561 -        FindInClass tst = new FindInClass(loader, null);
  33.562 -        cr.accept(tst, 0);
  33.563 -        if (tst.found > 0) {
  33.564 -            ClassWriter w = new ClassWriterEx(loader, cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
  33.565 -            FindInClass fic = new FindInClass(loader, w);
  33.566 -            cr.accept(fic, 0);
  33.567 -            arr = w.toByteArray();
  33.568 -        }
  33.569 -        return arr;
  33.570 -    }
  33.571 -
  33.572 -    private static final class TrueFn extends Fn {
  33.573 -        @Override
  33.574 -        public Object invoke(Object thiz, Object... args) throws Exception {
  33.575 -            return Boolean.TRUE;
  33.576 -        }
  33.577 -    } // end of TrueFn
  33.578 -}
    34.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/JavaScriptProcesor.java	Mon Dec 16 17:16:02 2013 +0100
    34.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.3 @@ -1,347 +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.IOException;
   34.27 -import java.io.Writer;
   34.28 -import java.util.Collections;
   34.29 -import java.util.HashMap;
   34.30 -import java.util.HashSet;
   34.31 -import java.util.List;
   34.32 -import java.util.Map;
   34.33 -import java.util.Set;
   34.34 -import java.util.TreeMap;
   34.35 -import javax.annotation.processing.AbstractProcessor;
   34.36 -import javax.annotation.processing.Completion;
   34.37 -import javax.annotation.processing.Completions;
   34.38 -import javax.annotation.processing.Messager;
   34.39 -import javax.annotation.processing.Processor;
   34.40 -import javax.annotation.processing.RoundEnvironment;
   34.41 -import javax.lang.model.SourceVersion;
   34.42 -import javax.lang.model.element.AnnotationMirror;
   34.43 -import javax.lang.model.element.Element;
   34.44 -import javax.lang.model.element.ElementKind;
   34.45 -import javax.lang.model.element.ExecutableElement;
   34.46 -import javax.lang.model.element.Modifier;
   34.47 -import javax.lang.model.element.PackageElement;
   34.48 -import javax.lang.model.element.TypeElement;
   34.49 -import javax.lang.model.element.VariableElement;
   34.50 -import javax.lang.model.type.ArrayType;
   34.51 -import javax.lang.model.type.ExecutableType;
   34.52 -import javax.lang.model.type.TypeKind;
   34.53 -import javax.lang.model.type.TypeMirror;
   34.54 -import javax.tools.Diagnostic;
   34.55 -import javax.tools.FileObject;
   34.56 -import javax.tools.StandardLocation;
   34.57 -import net.java.html.js.JavaScriptBody;
   34.58 -import net.java.html.js.JavaScriptResource;
   34.59 -import org.openide.util.lookup.ServiceProvider;
   34.60 -
   34.61 -/**
   34.62 - *
   34.63 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   34.64 - */
   34.65 -@ServiceProvider(service = Processor.class)
   34.66 -public final class JavaScriptProcesor extends AbstractProcessor {
   34.67 -    private final Map<String,Map<String,ExecutableElement>> javacalls = 
   34.68 -        new HashMap<String,Map<String,ExecutableElement>>();
   34.69 -    
   34.70 -    @Override
   34.71 -    public Set<String> getSupportedAnnotationTypes() {
   34.72 -        Set<String> set = new HashSet<String>();
   34.73 -        set.add(JavaScriptBody.class.getName());
   34.74 -        set.add(JavaScriptResource.class.getName());
   34.75 -        return set;
   34.76 -    }
   34.77 -    
   34.78 -    @Override
   34.79 -    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
   34.80 -        final Messager msg = processingEnv.getMessager();
   34.81 -        for (Element e : roundEnv.getElementsAnnotatedWith(JavaScriptBody.class)) {
   34.82 -            if (e.getKind() != ElementKind.METHOD && e.getKind() != ElementKind.CONSTRUCTOR) {
   34.83 -                continue;
   34.84 -            }
   34.85 -            ExecutableElement ee = (ExecutableElement)e;
   34.86 -            List<? extends VariableElement> params = ee.getParameters();
   34.87 -            
   34.88 -            JavaScriptBody jsb = e.getAnnotation(JavaScriptBody.class);
   34.89 -            if (jsb == null) {
   34.90 -                continue;
   34.91 -            }
   34.92 -            String[] arr = jsb.args();
   34.93 -            if (params.size() != arr.length) {
   34.94 -                msg.printMessage(Diagnostic.Kind.ERROR, "Number of args arguments does not match real arguments!", e);
   34.95 -            }
   34.96 -            if (!jsb.javacall() && jsb.body().contains(".@")) {
   34.97 -                msg.printMessage(Diagnostic.Kind.WARNING, "Usage of .@ usually requires javacall=true", e);
   34.98 -            }
   34.99 -            if (jsb.javacall()) {
  34.100 -                JsCallback verify = new VerifyCallback(e);
  34.101 -                try {
  34.102 -                    verify.parse(jsb.body());
  34.103 -                } catch (IllegalStateException ex) {
  34.104 -                    msg.printMessage(Diagnostic.Kind.ERROR, ex.getLocalizedMessage(), e);
  34.105 -                }
  34.106 -            }
  34.107 -        }
  34.108 -        for (Element e : roundEnv.getElementsAnnotatedWith(JavaScriptResource.class)) {
  34.109 -            JavaScriptResource r = e.getAnnotation(JavaScriptResource.class);
  34.110 -            if (r == null) {
  34.111 -                continue;
  34.112 -            }
  34.113 -            final String res;
  34.114 -            if (r.value().startsWith("/")) {
  34.115 -                res = r.value();
  34.116 -            } else {
  34.117 -                res = findPkg(e).replace('.', '/') + "/" + r.value();
  34.118 -            }
  34.119 -            
  34.120 -            try {
  34.121 -                FileObject os = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", res);
  34.122 -                os.openInputStream().close();
  34.123 -            } catch (IOException ex1) {
  34.124 -                try {
  34.125 -                    FileObject os2 = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", res);
  34.126 -                    os2.openInputStream().close();
  34.127 -                } catch (IOException ex2) {
  34.128 -                    msg.printMessage(Diagnostic.Kind.ERROR, "Cannot find " + res + " in " + res + " package", e);
  34.129 -                }
  34.130 -            }
  34.131 -        }
  34.132 -
  34.133 -        if (roundEnv.processingOver()) {
  34.134 -            generateCallbackClass(javacalls);
  34.135 -            javacalls.clear();
  34.136 -        }
  34.137 -        return true;
  34.138 -    }
  34.139 -
  34.140 -    @Override
  34.141 -    public Iterable<? extends Completion> getCompletions(Element e, 
  34.142 -        AnnotationMirror annotation, ExecutableElement member, String userText
  34.143 -    ) {
  34.144 -        StringBuilder sb = new StringBuilder();
  34.145 -        if (e.getKind() == ElementKind.METHOD && member.getSimpleName().contentEquals("args")) {
  34.146 -            ExecutableElement ee = (ExecutableElement) e;
  34.147 -            String sep = "";
  34.148 -            sb.append("{ ");
  34.149 -            for (VariableElement ve : ee.getParameters()) {
  34.150 -                sb.append(sep).append('"').append(ve.getSimpleName())
  34.151 -                    .append('"');
  34.152 -                sep = ", ";
  34.153 -            }
  34.154 -            sb.append(" }");
  34.155 -            return Collections.nCopies(1, Completions.of(sb.toString()));
  34.156 -        }
  34.157 -        return null;
  34.158 -    }
  34.159 -
  34.160 -    private class VerifyCallback extends JsCallback {
  34.161 -        private final Element e;
  34.162 -        public VerifyCallback(Element e) {
  34.163 -            this.e = e;
  34.164 -        }
  34.165 -
  34.166 -        @Override
  34.167 -        protected CharSequence callMethod(String ident, String fqn, String method, String params) {
  34.168 -            final TypeElement type = processingEnv.getElementUtils().getTypeElement(fqn);
  34.169 -            if (type == null) {
  34.170 -                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, 
  34.171 -                    "Callback to non-existing class " + fqn, e
  34.172 -                );
  34.173 -                return "";
  34.174 -            }
  34.175 -            ExecutableElement found = null;
  34.176 -            StringBuilder foundParams = new StringBuilder();
  34.177 -            for (Element m : type.getEnclosedElements()) {
  34.178 -                if (m.getKind() != ElementKind.METHOD) {
  34.179 -                    continue;
  34.180 -                }
  34.181 -                if (m.getSimpleName().contentEquals(method)) {
  34.182 -                    String paramTypes = findParamTypes((ExecutableElement)m);
  34.183 -                    if (paramTypes.equals(params)) {
  34.184 -                        found = (ExecutableElement) m;
  34.185 -                        break;
  34.186 -                    }
  34.187 -                    foundParams.append(paramTypes).append("\n");
  34.188 -                }
  34.189 -            }
  34.190 -            if (found == null) {
  34.191 -                if (foundParams.length() == 0) {
  34.192 -                    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, 
  34.193 -                        "Callback to class " + fqn + " with unknown method " + method, e
  34.194 -                    );
  34.195 -                } else {
  34.196 -                    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, 
  34.197 -                        "Callback to " + fqn + "." + method + " with wrong parameters: " + 
  34.198 -                        params + ". Only known parameters are " + foundParams, e
  34.199 -                    );
  34.200 -                }
  34.201 -            } else {
  34.202 -                Map<String,ExecutableElement> mangledOnes = javacalls.get(findPkg(e));
  34.203 -                if (mangledOnes == null) {
  34.204 -                    mangledOnes = new TreeMap<String, ExecutableElement>();
  34.205 -                    javacalls.put(findPkg(e), mangledOnes);
  34.206 -                }
  34.207 -                String mangled = JsCallback.mangle(fqn, method, findParamTypes(found));
  34.208 -                mangledOnes.put(mangled, found);
  34.209 -            }
  34.210 -            return "";
  34.211 -        }
  34.212 -
  34.213 -        private String findParamTypes(ExecutableElement method) {
  34.214 -            ExecutableType t = (ExecutableType) method.asType();
  34.215 -            StringBuilder sb = new StringBuilder();
  34.216 -            sb.append('(');
  34.217 -            for (TypeMirror tm : t.getParameterTypes()) {
  34.218 -                if (tm.getKind().isPrimitive()) {
  34.219 -                    switch (tm.getKind()) {
  34.220 -                        case INT: sb.append('I'); break;
  34.221 -                        case BOOLEAN: sb.append('Z'); break;
  34.222 -                        case BYTE: sb.append('B'); break;
  34.223 -                        case CHAR: sb.append('C'); break;
  34.224 -                        case SHORT: sb.append('S'); break;
  34.225 -                        case DOUBLE: sb.append('D'); break;
  34.226 -                        case FLOAT: sb.append('F'); break;
  34.227 -                        case LONG: sb.append('J'); break;
  34.228 -                        default:
  34.229 -                            throw new IllegalStateException("Uknown " + tm.getKind());
  34.230 -                    }
  34.231 -                } else {
  34.232 -                    while (tm.getKind() == TypeKind.ARRAY) {
  34.233 -                        sb.append('[');
  34.234 -                        tm = ((ArrayType)tm).getComponentType();
  34.235 -                    }
  34.236 -                    sb.append('L');
  34.237 -                    sb.append(tm.toString().replace('.', '/'));
  34.238 -                    sb.append(';');
  34.239 -                }
  34.240 -            }
  34.241 -            sb.append(')');
  34.242 -            return sb.toString();
  34.243 -        }
  34.244 -    }
  34.245 -    
  34.246 -    private void generateCallbackClass(Map<String,Map<String, ExecutableElement>> process) {
  34.247 -        for (Map.Entry<String, Map<String, ExecutableElement>> pkgEn : process.entrySet()) {
  34.248 -            String pkgName = pkgEn.getKey();
  34.249 -            Map<String, ExecutableElement> map = pkgEn.getValue();
  34.250 -            StringBuilder source = new StringBuilder();
  34.251 -            source.append("package ").append(pkgName).append(";\n");
  34.252 -            source.append("public final class $JsCallbacks$ {\n");
  34.253 -            source.append("  static final $JsCallbacks$ VM = new $JsCallbacks$(null);\n");
  34.254 -            source.append("  private final org.apidesign.html.boot.spi.Fn.Presenter p;\n");
  34.255 -            source.append("  private $JsCallbacks$ last;\n");
  34.256 -            source.append("  private $JsCallbacks$(org.apidesign.html.boot.spi.Fn.Presenter p) {\n");
  34.257 -            source.append("    this.p = p;\n");
  34.258 -            source.append("  }\n");
  34.259 -            source.append("  final $JsCallbacks$ current() {\n");
  34.260 -            source.append("    org.apidesign.html.boot.spi.Fn.Presenter now = org.apidesign.html.boot.spi.Fn.activePresenter();\n");
  34.261 -            source.append("    if (now == p) return this;\n");
  34.262 -            source.append("    if (last != null && now == last.p) return last;\n");
  34.263 -            source.append("    return last = new $JsCallbacks$(now);\n");
  34.264 -            source.append("  }\n");
  34.265 -            for (Map.Entry<String, ExecutableElement> entry : map.entrySet()) {
  34.266 -                final String mangled = entry.getKey();
  34.267 -                final ExecutableElement m = entry.getValue();
  34.268 -                final boolean isStatic = m.getModifiers().contains(Modifier.STATIC);
  34.269 -                
  34.270 -                source.append("\n  public java.lang.Object ")
  34.271 -                    .append(mangled)
  34.272 -                    .append("(");
  34.273 -                
  34.274 -                String sep = "";
  34.275 -                if (!isStatic) {
  34.276 -                    source.append(((TypeElement)m.getEnclosingElement()).getQualifiedName());
  34.277 -                    source.append(" self");
  34.278 -                    sep = ", ";
  34.279 -                }
  34.280 -                
  34.281 -                int cnt = 0;
  34.282 -                for (VariableElement ve : m.getParameters()) {
  34.283 -                    source.append(sep);
  34.284 -                    source.append(ve.asType());
  34.285 -                    source.append(" arg").append(++cnt);
  34.286 -                    sep = ", ";
  34.287 -                }
  34.288 -                source.append(") throws Throwable {\n");
  34.289 -                if (processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_7) >= 0) {
  34.290 -                    source.append("    try (java.io.Closeable a = org.apidesign.html.boot.spi.Fn.activate(p)) { \n");
  34.291 -                } else {
  34.292 -                    source.append("    java.io.Closeable a = org.apidesign.html.boot.spi.Fn.activate(p); try {\n");
  34.293 -                }
  34.294 -                source.append("    ");
  34.295 -                if (m.getReturnType().getKind() != TypeKind.VOID) {
  34.296 -                    source.append("return ");
  34.297 -                }
  34.298 -                if (isStatic) {
  34.299 -                    source.append(((TypeElement)m.getEnclosingElement()).getQualifiedName());
  34.300 -                    source.append('.');
  34.301 -                } else {
  34.302 -                    source.append("self.");
  34.303 -                }
  34.304 -                source.append(m.getSimpleName());
  34.305 -                source.append("(");
  34.306 -                cnt = 0;
  34.307 -                sep = "";
  34.308 -                for (VariableElement ve : m.getParameters()) {
  34.309 -                    source.append(sep);
  34.310 -                    source.append("arg").append(++cnt);
  34.311 -                    sep = ", ";
  34.312 -                }
  34.313 -                source.append(");\n");
  34.314 -                if (m.getReturnType().getKind() == TypeKind.VOID) {
  34.315 -                    source.append("    return null;\n");
  34.316 -                }
  34.317 -                if (processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_7) >= 0) {
  34.318 -                    source.append("    }\n");
  34.319 -                } else {
  34.320 -                    
  34.321 -                    source.append("    } finally {\n");
  34.322 -                    source.append("      a.close();\n");
  34.323 -                    source.append("    }\n");
  34.324 -                }
  34.325 -                source.append("  }\n");
  34.326 -            }
  34.327 -            source.append("}\n");
  34.328 -            final String srcName = pkgName + ".$JsCallbacks$";
  34.329 -            try {
  34.330 -                Writer w = processingEnv.getFiler().createSourceFile(srcName,
  34.331 -                    map.values().toArray(new Element[map.size()])
  34.332 -                ).openWriter();
  34.333 -                w.write(source.toString());
  34.334 -                w.close();
  34.335 -            } catch (IOException ex) {
  34.336 -                processingEnv.getMessager().printMessage(
  34.337 -                    Diagnostic.Kind.ERROR, "Can't write " + srcName + ": " + ex.getMessage()
  34.338 -                );
  34.339 -            }
  34.340 -        }
  34.341 -    }
  34.342 -    
  34.343 -    private static String findPkg(Element e) {
  34.344 -        while (e.getKind() != ElementKind.PACKAGE) {
  34.345 -            e = e.getEnclosingElement();
  34.346 -        }
  34.347 -        return ((PackageElement)e).getQualifiedName().toString();
  34.348 -    }
  34.349 -    
  34.350 -}
    35.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/JsAgent.java	Mon Dec 16 17:16:02 2013 +0100
    35.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.3 @@ -1,45 +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.lang.instrument.ClassFileTransformer;
   35.27 -import java.lang.instrument.IllegalClassFormatException;
   35.28 -import java.lang.instrument.Instrumentation;
   35.29 -import java.security.ProtectionDomain;
   35.30 -
   35.31 -/**
   35.32 - *
   35.33 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   35.34 - */
   35.35 -public final class JsAgent implements ClassFileTransformer {
   35.36 -    public static void agentmain(String args, Instrumentation instr) {
   35.37 -        instr.addTransformer(new JsAgent());
   35.38 -    }
   35.39 -
   35.40 -    @Override
   35.41 -    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
   35.42 -        try {
   35.43 -            return FnUtils.transform(loader, classfileBuffer);
   35.44 -        } catch (Exception ex) {
   35.45 -            return classfileBuffer;
   35.46 -        }
   35.47 -    }
   35.48 -}
    36.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/JsCallback.java	Mon Dec 16 17:16:02 2013 +0100
    36.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.3 @@ -1,138 +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 -
   36.27 -/**
   36.28 - *
   36.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   36.30 - */
   36.31 -abstract class JsCallback {
   36.32 -    final String parse(String body) {
   36.33 -        StringBuilder sb = new StringBuilder();
   36.34 -        int pos = 0;
   36.35 -        for (;;) {
   36.36 -            int next = body.indexOf(".@", pos);
   36.37 -            if (next == -1) {
   36.38 -                sb.append(body.substring(pos));
   36.39 -                body = sb.toString();
   36.40 -                break;
   36.41 -            }
   36.42 -            int ident = next;
   36.43 -            while (ident > 0) {
   36.44 -                if (!Character.isJavaIdentifierPart(body.charAt(--ident))) {
   36.45 -                    ident++;
   36.46 -                    break;
   36.47 -                }
   36.48 -            }
   36.49 -            String refId = body.substring(ident, next);
   36.50 -            
   36.51 -            sb.append(body.substring(pos, ident));
   36.52 -            
   36.53 -            int sigBeg = body.indexOf('(', next);
   36.54 -            int sigEnd = body.indexOf(')', sigBeg);
   36.55 -            int colon4 = body.indexOf("::", next);
   36.56 -            if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
   36.57 -                throw new IllegalStateException(
   36.58 -                    "Wrong format of instance callback. "
   36.59 -                    + "Should be: 'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n" 
   36.60 -                    + body
   36.61 -                );
   36.62 -            }
   36.63 -            String fqn = body.substring(next + 2, colon4);
   36.64 -            String method = body.substring(colon4 + 2, sigBeg);
   36.65 -            String params = body.substring(sigBeg, sigEnd + 1);
   36.66 -
   36.67 -            int paramBeg = body.indexOf('(', sigEnd + 1);
   36.68 -            if (paramBeg == -1) {
   36.69 -                throw new IllegalStateException(
   36.70 -                    "Wrong format of instance callback. "
   36.71 -                    + "Should be: 'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n" 
   36.72 -                    + body
   36.73 -                );
   36.74 -            }
   36.75 -            
   36.76 -            sb.append(callMethod(refId, fqn, method, params));
   36.77 -            if (body.charAt(paramBeg + 1) != (')')) {
   36.78 -                sb.append(",");
   36.79 -            }
   36.80 -            pos = paramBeg + 1;
   36.81 -        }
   36.82 -        pos = 0;
   36.83 -        sb = null;
   36.84 -        for (;;) {
   36.85 -            int next = body.indexOf("@", pos);
   36.86 -            if (next == -1) {
   36.87 -                if (sb == null) {
   36.88 -                    return body;
   36.89 -                }
   36.90 -                sb.append(body.substring(pos));
   36.91 -                return sb.toString();
   36.92 -            }
   36.93 -            if (sb == null) {
   36.94 -                sb = new StringBuilder();
   36.95 -            }
   36.96 -            
   36.97 -            sb.append(body.substring(pos, next));
   36.98 -            
   36.99 -            int sigBeg = body.indexOf('(', next);
  36.100 -            int sigEnd = body.indexOf(')', sigBeg);
  36.101 -            int colon4 = body.indexOf("::", next);
  36.102 -            if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
  36.103 -                throw new IllegalStateException(
  36.104 -                    "Wrong format of static callback. "
  36.105 -                    + "Should be: '@pkg.Class::staticMethod(Ljava/lang/Object;)(param)':\n" 
  36.106 -                    + body
  36.107 -                );
  36.108 -            }
  36.109 -            String fqn = body.substring(next + 1, colon4);
  36.110 -            String method = body.substring(colon4 + 2, sigBeg);
  36.111 -            String params = body.substring(sigBeg, sigEnd + 1);
  36.112 -
  36.113 -            int paramBeg = body.indexOf('(', sigEnd + 1);
  36.114 -            
  36.115 -            sb.append(callMethod(null, fqn, method, params));
  36.116 -            pos = paramBeg + 1;
  36.117 -        }
  36.118 -    }
  36.119 -
  36.120 -    protected abstract CharSequence callMethod(
  36.121 -        String ident, String fqn, String method, String params
  36.122 -    );
  36.123 -
  36.124 -    static String mangle(String fqn, String method, String params) {
  36.125 -        if (params.startsWith("(")) {
  36.126 -            params = params.substring(1);
  36.127 -        }
  36.128 -        if (params.endsWith(")")) {
  36.129 -            params = params.substring(0, params.length() - 1);
  36.130 -        }
  36.131 -        return 
  36.132 -            replace(fqn) + "$" + replace(method) + "$" + replace(params);
  36.133 -    }
  36.134 -    
  36.135 -    private static String replace(String orig) {
  36.136 -        return orig.replace("_", "_1").
  36.137 -            replace(";", "_2").
  36.138 -            replace("[", "_3").
  36.139 -            replace('.', '_').replace('/', '_');
  36.140 -    }
  36.141 -}
    37.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/JsClassLoader.java	Mon Dec 16 17:16:02 2013 +0100
    37.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.3 @@ -1,111 +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 org.apidesign.html.boot.spi.Fn;
   37.27 -import java.io.IOException;
   37.28 -import java.io.InputStream;
   37.29 -import java.io.Reader;
   37.30 -import java.net.URL;
   37.31 -import java.util.Enumeration;
   37.32 -
   37.33 -/** 
   37.34 - *
   37.35 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   37.36 - */
   37.37 -abstract class JsClassLoader extends ClassLoader {
   37.38 -    JsClassLoader(ClassLoader parent) {
   37.39 -        super(parent);
   37.40 -        setDefaultAssertionStatus(JsClassLoader.class.desiredAssertionStatus());
   37.41 -    }
   37.42 -    
   37.43 -    @Override
   37.44 -    protected abstract URL findResource(String name);
   37.45 -    
   37.46 -    @Override
   37.47 -    protected abstract Enumeration<URL> findResources(String name);
   37.48 -
   37.49 -    @Override
   37.50 -    protected Class<?> findClass(String name) throws ClassNotFoundException {
   37.51 -        if (name.startsWith("javafx")) {
   37.52 -            return Class.forName(name);
   37.53 -        }
   37.54 -        if (name.startsWith("netscape")) {
   37.55 -            return Class.forName(name);
   37.56 -        }
   37.57 -        if (name.startsWith("com.sun")) {
   37.58 -            return Class.forName(name);
   37.59 -        }
   37.60 -        if (name.equals(JsClassLoader.class.getName())) {
   37.61 -            return JsClassLoader.class;
   37.62 -        }
   37.63 -        if (name.equals(Fn.class.getName())) {
   37.64 -            return Fn.class;
   37.65 -        }
   37.66 -        if (name.equals(Fn.Presenter.class.getName())) {
   37.67 -            return Fn.Presenter.class;
   37.68 -        }
   37.69 -        if (name.equals(FnUtils.class.getName())) {
   37.70 -            return FnUtils.class;
   37.71 -        }
   37.72 -        if (
   37.73 -            name.equals("org.apidesign.html.boot.spi.Fn") ||
   37.74 -            name.equals("org.apidesign.html.boot.impl.FnUtils") ||
   37.75 -            name.equals("org.apidesign.html.boot.impl.FnContext")
   37.76 -        ) {
   37.77 -            return Class.forName(name);
   37.78 -        }
   37.79 -        URL u = findResource(name.replace('.', '/') + ".class");
   37.80 -        if (u != null) {
   37.81 -            InputStream is = null;
   37.82 -            try {
   37.83 -                is = u.openStream();
   37.84 -                byte[] arr = new byte[is.available()];
   37.85 -                int len = 0;
   37.86 -                while (len < arr.length) {
   37.87 -                    int read = is.read(arr, len, arr.length - len);
   37.88 -                    if (read == -1) {
   37.89 -                        throw new IOException("Can't read " + u);
   37.90 -                    }
   37.91 -                    len += read;
   37.92 -                }
   37.93 -                is.close();
   37.94 -                is = null;
   37.95 -                arr = FnUtils.transform(JsClassLoader.this, arr);
   37.96 -                if (arr != null) {
   37.97 -                    return defineClass(name, arr, 0, arr.length);
   37.98 -                }
   37.99 -            } catch (IOException ex) {
  37.100 -                throw new ClassNotFoundException("Can't load " + name, ex);
  37.101 -            } finally {
  37.102 -                try {
  37.103 -                    if (is != null) is.close();
  37.104 -                } catch (IOException ex) {
  37.105 -                    throw new ClassNotFoundException(null, ex);
  37.106 -                }
  37.107 -            }
  37.108 -        }
  37.109 -        return super.findClass(name);
  37.110 -    }
  37.111 -    
  37.112 -    protected abstract Fn defineFn(String code, String... names);
  37.113 -    protected abstract void loadScript(Reader code) throws Exception;
  37.114 -}
    38.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/Test.java	Mon Dec 16 17:16:02 2013 +0100
    38.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.3 @@ -1,35 +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 -import java.util.concurrent.Callable;
   38.27 -import net.java.html.js.JavaScriptBody;
   38.28 -
   38.29 -/**
   38.30 - *
   38.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   38.32 - */
   38.33 -public final class Test implements Callable<Boolean> {
   38.34 -    @Override @JavaScriptBody(args = {}, body = "return true;")
   38.35 -    public Boolean call() {
   38.36 -        return false;
   38.37 -    }
   38.38 -}
    39.1 --- a/boot/src/main/java/org/apidesign/html/boot/spi/Fn.java	Mon Dec 16 17:16:02 2013 +0100
    39.2 +++ b/boot/src/main/java/org/apidesign/html/boot/spi/Fn.java	Mon Dec 16 17:16:40 2013 +0100
    39.3 @@ -1,22 +1,44 @@
    39.4  /**
    39.5 - * HTML via Java(tm) Language Bindings
    39.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    39.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    39.8   *
    39.9 - * This program is free software: you can redistribute it and/or modify
   39.10 - * it under the terms of the GNU General Public License as published by
   39.11 - * the Free Software Foundation, version 2 of the License.
   39.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   39.13   *
   39.14 - * This program is distributed in the hope that it will be useful,
   39.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   39.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   39.17 - * GNU General Public License for more details. apidesign.org
   39.18 - * designates this particular file as subject to the
   39.19 - * "Classpath" exception as provided by apidesign.org
   39.20 - * in the License file that accompanied this code.
   39.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   39.22 + * Other names may be trademarks of their respective owners.
   39.23   *
   39.24 - * You should have received a copy of the GNU General Public License
   39.25 - * along with this program. Look for COPYING file in the top folder.
   39.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   39.27 + * The contents of this file are subject to the terms of either the GNU
   39.28 + * General Public License Version 2 only ("GPL") or the Common
   39.29 + * Development and Distribution License("CDDL") (collectively, the
   39.30 + * "License"). You may not use this file except in compliance with the
   39.31 + * License. You can obtain a copy of the License at
   39.32 + * http://www.netbeans.org/cddl-gplv2.html
   39.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   39.34 + * specific language governing permissions and limitations under the
   39.35 + * License.  When distributing the software, include this License Header
   39.36 + * Notice in each file and include the License file at
   39.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   39.38 + * particular file as subject to the "Classpath" exception as provided
   39.39 + * by Oracle in the GPL Version 2 section of the License file that
   39.40 + * accompanied this code. If applicable, add the following below the
   39.41 + * License Header, with the fields enclosed by brackets [] replaced by
   39.42 + * your own identifying information:
   39.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   39.44 + *
   39.45 + * Contributor(s):
   39.46 + *
   39.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   39.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   39.49 + *
   39.50 + * If you wish your version of this file to be governed by only the CDDL
   39.51 + * or only the GPL Version 2, indicate your decision by adding
   39.52 + * "[Contributor] elects to include this software in this distribution
   39.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   39.54 + * single choice of license, a recipient has the option to distribute
   39.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   39.56 + * to extend the choice of license to its licensees as provided above.
   39.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   39.58 + * Version 2 license, then the option applies only if the new code is
   39.59 + * made subject to such option by the copyright holder.
   39.60   */
   39.61  package org.apidesign.html.boot.spi;
   39.62  
   39.63 @@ -29,9 +51,8 @@
   39.64  import java.util.HashSet;
   39.65  import java.util.Map;
   39.66  import java.util.Set;
   39.67 -import java.util.WeakHashMap;
   39.68  import net.java.html.js.JavaScriptBody;
   39.69 -import org.apidesign.html.boot.impl.FnContext;
   39.70 +import org.netbeans.html.boot.impl.FnContext;
   39.71  
   39.72  /** Represents single JavaScript function that can be invoked. 
   39.73   * Created via {@link Presenter#defineFn(java.lang.String, java.lang.String...)}.
    40.1 --- a/boot/src/main/java/org/apidesign/html/boot/spi/package.html	Mon Dec 16 17:16:02 2013 +0100
    40.2 +++ b/boot/src/main/java/org/apidesign/html/boot/spi/package.html	Mon Dec 16 17:16:40 2013 +0100
    40.3 @@ -1,23 +1,45 @@
    40.4  <!--
    40.5  
    40.6 -    HTML via Java(tm) Language Bindings
    40.7 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    40.8 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    40.9  
   40.10 -    This program is free software: you can redistribute it and/or modify
   40.11 -    it under the terms of the GNU General Public License as published by
   40.12 -    the Free Software Foundation, version 2 of the License.
   40.13 +    Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   40.14  
   40.15 -    This program is distributed in the hope that it will be useful,
   40.16 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   40.17 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   40.18 -    GNU General Public License for more details. apidesign.org
   40.19 -    designates this particular file as subject to the
   40.20 -    "Classpath" exception as provided by apidesign.org
   40.21 -    in the License file that accompanied this code.
   40.22 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   40.23 +    Other names may be trademarks of their respective owners.
   40.24  
   40.25 -    You should have received a copy of the GNU General Public License
   40.26 -    along with this program. Look for COPYING file in the top folder.
   40.27 -    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   40.28 +    The contents of this file are subject to the terms of either the GNU
   40.29 +    General Public License Version 2 only ("GPL") or the Common
   40.30 +    Development and Distribution License("CDDL") (collectively, the
   40.31 +    "License"). You may not use this file except in compliance with the
   40.32 +    License. You can obtain a copy of the License at
   40.33 +    http://www.netbeans.org/cddl-gplv2.html
   40.34 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   40.35 +    specific language governing permissions and limitations under the
   40.36 +    License.  When distributing the software, include this License Header
   40.37 +    Notice in each file and include the License file at
   40.38 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   40.39 +    particular file as subject to the "Classpath" exception as provided
   40.40 +    by Oracle in the GPL Version 2 section of the License file that
   40.41 +    accompanied this code. If applicable, add the following below the
   40.42 +    License Header, with the fields enclosed by brackets [] replaced by
   40.43 +    your own identifying information:
   40.44 +    "Portions Copyrighted [year] [name of copyright owner]"
   40.45 +
   40.46 +    Contributor(s):
   40.47 +
   40.48 +    The Original Software is NetBeans. The Initial Developer of the Original
   40.49 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   40.50 +
   40.51 +    If you wish your version of this file to be governed by only the CDDL
   40.52 +    or only the GPL Version 2, indicate your decision by adding
   40.53 +    "[Contributor] elects to include this software in this distribution
   40.54 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
   40.55 +    single choice of license, a recipient has the option to distribute
   40.56 +    your version of this file under either the CDDL, the GPL Version 2 or
   40.57 +    to extend the choice of license to its licensees as provided above.
   40.58 +    However, if you add GPL Version 2 code and therefore, elected the GPL
   40.59 +    Version 2 license, then the option applies only if the new code is
   40.60 +    made subject to such option by the copyright holder.
   40.61  
   40.62  -->
   40.63  <!DOCTYPE html>
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/FindResources.java	Mon Dec 16 17:16:40 2013 +0100
    41.3 @@ -0,0 +1,56 @@
    41.4 +/**
    41.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    41.6 + *
    41.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    41.8 + *
    41.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   41.10 + * Other names may be trademarks of their respective owners.
   41.11 + *
   41.12 + * The contents of this file are subject to the terms of either the GNU
   41.13 + * General Public License Version 2 only ("GPL") or the Common
   41.14 + * Development and Distribution License("CDDL") (collectively, the
   41.15 + * "License"). You may not use this file except in compliance with the
   41.16 + * License. You can obtain a copy of the License at
   41.17 + * http://www.netbeans.org/cddl-gplv2.html
   41.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   41.19 + * specific language governing permissions and limitations under the
   41.20 + * License.  When distributing the software, include this License Header
   41.21 + * Notice in each file and include the License file at
   41.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   41.23 + * particular file as subject to the "Classpath" exception as provided
   41.24 + * by Oracle in the GPL Version 2 section of the License file that
   41.25 + * accompanied this code. If applicable, add the following below the
   41.26 + * License Header, with the fields enclosed by brackets [] replaced by
   41.27 + * your own identifying information:
   41.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   41.29 + *
   41.30 + * Contributor(s):
   41.31 + *
   41.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   41.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   41.34 + *
   41.35 + * If you wish your version of this file to be governed by only the CDDL
   41.36 + * or only the GPL Version 2, indicate your decision by adding
   41.37 + * "[Contributor] elects to include this software in this distribution
   41.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   41.39 + * single choice of license, a recipient has the option to distribute
   41.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   41.41 + * to extend the choice of license to its licensees as provided above.
   41.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   41.43 + * Version 2 license, then the option applies only if the new code is
   41.44 + * made subject to such option by the copyright holder.
   41.45 + */
   41.46 +package org.netbeans.html.boot.impl;
   41.47 +
   41.48 +import java.net.URL;
   41.49 +import java.util.Collection;
   41.50 +
   41.51 +/**
   41.52 + *
   41.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   41.54 + */
   41.55 +public interface FindResources {
   41.56 +
   41.57 +    public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough);
   41.58 +    
   41.59 +}
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/FnContext.java	Mon Dec 16 17:16:40 2013 +0100
    42.3 @@ -0,0 +1,98 @@
    42.4 +/**
    42.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    42.6 + *
    42.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    42.8 + *
    42.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   42.10 + * Other names may be trademarks of their respective owners.
   42.11 + *
   42.12 + * The contents of this file are subject to the terms of either the GNU
   42.13 + * General Public License Version 2 only ("GPL") or the Common
   42.14 + * Development and Distribution License("CDDL") (collectively, the
   42.15 + * "License"). You may not use this file except in compliance with the
   42.16 + * License. You can obtain a copy of the License at
   42.17 + * http://www.netbeans.org/cddl-gplv2.html
   42.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   42.19 + * specific language governing permissions and limitations under the
   42.20 + * License.  When distributing the software, include this License Header
   42.21 + * Notice in each file and include the License file at
   42.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   42.23 + * particular file as subject to the "Classpath" exception as provided
   42.24 + * by Oracle in the GPL Version 2 section of the License file that
   42.25 + * accompanied this code. If applicable, add the following below the
   42.26 + * License Header, with the fields enclosed by brackets [] replaced by
   42.27 + * your own identifying information:
   42.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   42.29 + *
   42.30 + * Contributor(s):
   42.31 + *
   42.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   42.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   42.34 + *
   42.35 + * If you wish your version of this file to be governed by only the CDDL
   42.36 + * or only the GPL Version 2, indicate your decision by adding
   42.37 + * "[Contributor] elects to include this software in this distribution
   42.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   42.39 + * single choice of license, a recipient has the option to distribute
   42.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   42.41 + * to extend the choice of license to its licensees as provided above.
   42.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   42.43 + * Version 2 license, then the option applies only if the new code is
   42.44 + * made subject to such option by the copyright holder.
   42.45 + */
   42.46 +package org.netbeans.html.boot.impl;
   42.47 +
   42.48 +import java.io.Closeable;
   42.49 +import java.io.IOException;
   42.50 +import java.util.logging.Logger;
   42.51 +import org.apidesign.html.boot.spi.Fn;
   42.52 +
   42.53 +/**
   42.54 + *
   42.55 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   42.56 + */
   42.57 +public final class FnContext implements Closeable {
   42.58 +    private static final Logger LOG = Logger.getLogger(FnContext.class.getName());
   42.59 +
   42.60 +    private Object prev;
   42.61 +    private FnContext(Fn.Presenter p) {
   42.62 +        this.prev = p;
   42.63 +    }
   42.64 +
   42.65 +    @Override
   42.66 +    public void close() throws IOException {
   42.67 +        if (prev != this) {
   42.68 +            currentPresenter((Fn.Presenter)prev);
   42.69 +            prev = this;
   42.70 +        }
   42.71 +    }
   42.72 +/*
   42.73 +    @Override
   42.74 +    protected void finalize() throws Throwable {
   42.75 +        if (prev != null) {
   42.76 +            LOG.warning("Unclosed context!");
   42.77 +        }
   42.78 +    }
   42.79 +*/
   42.80 +    public static Closeable activate(Fn.Presenter newP) {
   42.81 +        return new FnContext(currentPresenter(newP));
   42.82 +    }
   42.83 +    
   42.84 +    
   42.85 +    private static final ThreadLocal<Fn.Presenter> CURRENT = new ThreadLocal<Fn.Presenter>();
   42.86 +
   42.87 +    public static Fn.Presenter currentPresenter(Fn.Presenter p) {
   42.88 +        Fn.Presenter prev = CURRENT.get();
   42.89 +        CURRENT.set(p);
   42.90 +        return prev;
   42.91 +    }
   42.92 +
   42.93 +    public static Fn.Presenter currentPresenter() {
   42.94 +        Fn.Presenter p = CURRENT.get();
   42.95 +        if (p == null) {
   42.96 +            throw new IllegalStateException("No current WebView context around!");
   42.97 +        }
   42.98 +        return p;
   42.99 +    }
  42.100 +    
  42.101 +}
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/FnUtils.java	Mon Dec 16 17:16:40 2013 +0100
    43.3 @@ -0,0 +1,597 @@
    43.4 +/**
    43.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    43.6 + *
    43.7 + * Copyright 1997-2010 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.io.Closeable;
   43.49 +import java.io.InputStream;
   43.50 +import java.io.InputStreamReader;
   43.51 +import java.io.Reader;
   43.52 +import java.net.URL;
   43.53 +import java.util.ArrayList;
   43.54 +import java.util.Collections;
   43.55 +import java.util.Enumeration;
   43.56 +import java.util.List;
   43.57 +import java.util.concurrent.Callable;
   43.58 +import org.apidesign.html.boot.spi.Fn;
   43.59 +import org.objectweb.asm.AnnotationVisitor;
   43.60 +import org.objectweb.asm.ClassReader;
   43.61 +import org.objectweb.asm.ClassVisitor;
   43.62 +import org.objectweb.asm.ClassWriter;
   43.63 +import org.objectweb.asm.Label;
   43.64 +import org.objectweb.asm.MethodVisitor;
   43.65 +import org.objectweb.asm.Opcodes;
   43.66 +import org.objectweb.asm.Type;
   43.67 +import org.objectweb.asm.signature.SignatureReader;
   43.68 +import org.objectweb.asm.signature.SignatureVisitor;
   43.69 +import org.objectweb.asm.signature.SignatureWriter;
   43.70 +
   43.71 +/**
   43.72 + *
   43.73 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   43.74 + */
   43.75 +public final class FnUtils implements Fn.Presenter {
   43.76 +    
   43.77 +    private FnUtils() {
   43.78 +    }
   43.79 +    
   43.80 +    public static boolean isJavaScriptCapable(ClassLoader l) {
   43.81 +        if (l instanceof JsClassLoader) {
   43.82 +            return true;
   43.83 +        }
   43.84 +        Class<?> clazz;
   43.85 +        try (Closeable c = Fn.activate(new FnUtils())) {
   43.86 +            clazz = Class.forName(Test.class.getName(), true, l);
   43.87 +            final Object is = ((Callable<?>)clazz.newInstance()).call();
   43.88 +            return Boolean.TRUE.equals(is);
   43.89 +        } catch (Exception ex) {
   43.90 +            return false;
   43.91 +        }
   43.92 +    }
   43.93 +    
   43.94 +    public static boolean isValid(Fn fn) {
   43.95 +        return fn != null && fn.isValid();
   43.96 +    }
   43.97 +
   43.98 +    public static ClassLoader newLoader(final FindResources f, final Fn.Presenter d, ClassLoader parent) {
   43.99 +        return new JsClassLoader(parent) {
  43.100 +            @Override
  43.101 +            protected URL findResource(String name) {
  43.102 +                List<URL> l = res(name, true);
  43.103 +                return l.isEmpty() ? null : l.get(0);
  43.104 +            }
  43.105 +            
  43.106 +            @Override
  43.107 +            protected Enumeration<URL> findResources(String name) {
  43.108 +                return Collections.enumeration(res(name, false));
  43.109 +            }
  43.110 +            
  43.111 +            private List<URL> res(String name, boolean oneIsEnough) {
  43.112 +                List<URL> l = new ArrayList<URL>();
  43.113 +                f.findResources(name, l, oneIsEnough);
  43.114 +                return l;
  43.115 +            }
  43.116 +            
  43.117 +            @Override
  43.118 +            protected Fn defineFn(String code, String... names) {
  43.119 +                return d.defineFn(code, names);
  43.120 +            }
  43.121 +
  43.122 +            @Override
  43.123 +            protected void loadScript(Reader code) throws Exception {
  43.124 +                d.loadScript(code);
  43.125 +            }
  43.126 +        };
  43.127 +    }
  43.128 +
  43.129 +    static String callback(final String body) {
  43.130 +        return new JsCallback() {
  43.131 +            @Override
  43.132 +            protected CharSequence callMethod(
  43.133 +                String ident, String fqn, String method, String params
  43.134 +            ) {
  43.135 +                StringBuilder sb = new StringBuilder();
  43.136 +                sb.append("vm.").append(mangle(fqn, method, params));
  43.137 +                sb.append("(");
  43.138 +                if (ident != null) {
  43.139 +                    sb.append(ident);
  43.140 +                }
  43.141 +                return sb;
  43.142 +            }
  43.143 +
  43.144 +        }.parse(body);
  43.145 +    }
  43.146 +
  43.147 +    static void loadScript(ClassLoader jcl, String resource) {
  43.148 +        final InputStream script = jcl.getResourceAsStream(resource);
  43.149 +        if (script == null) {
  43.150 +            throw new NullPointerException("Can't find " + resource);
  43.151 +        }
  43.152 +        try {
  43.153 +            Reader isr = null;
  43.154 +            try {
  43.155 +                isr = new InputStreamReader(script, "UTF-8");
  43.156 +                FnContext.currentPresenter().loadScript(isr);
  43.157 +            } finally {
  43.158 +                if (isr != null) {
  43.159 +                    isr.close();
  43.160 +                }
  43.161 +            }
  43.162 +        } catch (Exception ex) {
  43.163 +            throw new IllegalStateException("Can't execute " + resource, ex);
  43.164 +        } 
  43.165 +    }
  43.166 +
  43.167 +    @Override
  43.168 +    public Fn defineFn(String code, String... names) {
  43.169 +        return new TrueFn();
  43.170 +    }
  43.171 +
  43.172 +    @Override
  43.173 +    public void displayPage(URL page, Runnable onPageLoad) {
  43.174 +    }
  43.175 +
  43.176 +    @Override
  43.177 +    public void loadScript(Reader code) throws Exception {
  43.178 +    }
  43.179 +    
  43.180 +    private static final class FindInClass extends ClassVisitor {
  43.181 +        private String name;
  43.182 +        private int found;
  43.183 +        private ClassLoader loader;
  43.184 +        private String resource;
  43.185 +
  43.186 +        public FindInClass(ClassLoader l, ClassVisitor cv) {
  43.187 +            super(Opcodes.ASM4, cv);
  43.188 +            this.loader = l;
  43.189 +        }
  43.190 +
  43.191 +        @Override
  43.192 +        public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
  43.193 +            this.name = name;
  43.194 +            super.visit(version, access, name, signature, superName, interfaces);
  43.195 +        }
  43.196 +
  43.197 +        @Override
  43.198 +        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
  43.199 +            if ("Lnet/java/html/js/JavaScriptResource;".equals(desc)) {
  43.200 +                return new LoadResource();
  43.201 +            }
  43.202 +            return super.visitAnnotation(desc, visible);
  43.203 +        }
  43.204 +
  43.205 +        @Override
  43.206 +        public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
  43.207 +            return new FindInMethod(access, name, desc,
  43.208 +                    super.visitMethod(access & (~Opcodes.ACC_NATIVE), name, desc, signature, exceptions)
  43.209 +            );
  43.210 +        }
  43.211 +
  43.212 +        private final class FindInMethod extends MethodVisitor {
  43.213 +
  43.214 +            private final String name;
  43.215 +            private final String desc;
  43.216 +            private final int access;
  43.217 +            private List<String> args;
  43.218 +            private String body;
  43.219 +            private boolean bodyGenerated;
  43.220 +
  43.221 +            public FindInMethod(int access, String name, String desc, MethodVisitor mv) {
  43.222 +                super(Opcodes.ASM4, mv);
  43.223 +                this.access = access;
  43.224 +                this.name = name;
  43.225 +                this.desc = desc;
  43.226 +            }
  43.227 +
  43.228 +            @Override
  43.229 +            public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
  43.230 +                if ("Lnet/java/html/js/JavaScriptBody;".equals(desc) // NOI18N
  43.231 +                        || "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;".equals(desc) // NOI18N
  43.232 +                        ) {
  43.233 +                    found++;
  43.234 +                    return new FindInAnno();
  43.235 +                }
  43.236 +                return super.visitAnnotation(desc, visible);
  43.237 +            }
  43.238 +
  43.239 +            private void generateJSBody(List<String> args, String body) {
  43.240 +                this.args = args;
  43.241 +                this.body = body;
  43.242 +            }
  43.243 +
  43.244 +            @Override
  43.245 +            public void visitCode() {
  43.246 +                if (body == null) {
  43.247 +                    return;
  43.248 +                }
  43.249 +                generateBody();
  43.250 +            }
  43.251 +
  43.252 +            private boolean generateBody() {
  43.253 +                if (bodyGenerated) {
  43.254 +                    return false;
  43.255 +                }
  43.256 +                bodyGenerated = true;
  43.257 +
  43.258 +                super.visitFieldInsn(
  43.259 +                        Opcodes.GETSTATIC, FindInClass.this.name,
  43.260 +                        "$$fn$$" + name + "_" + found,
  43.261 +                        "Lorg/apidesign/html/boot/spi/Fn;"
  43.262 +                );
  43.263 +                super.visitInsn(Opcodes.DUP);
  43.264 +                super.visitMethodInsn(
  43.265 +                        Opcodes.INVOKESTATIC,
  43.266 +                        "org/apidesign/html/boot/spi/Fn", "isValid",
  43.267 +                        "(Lorg/apidesign/html/boot/spi/Fn;)Z"
  43.268 +                );
  43.269 +                Label ifNotNull = new Label();
  43.270 +                super.visitJumpInsn(Opcodes.IFNE, ifNotNull);
  43.271 +
  43.272 +                // init Fn
  43.273 +                super.visitInsn(Opcodes.POP);
  43.274 +                super.visitLdcInsn(Type.getObjectType(FindInClass.this.name));
  43.275 +                super.visitLdcInsn(body);
  43.276 +                super.visitIntInsn(Opcodes.SIPUSH, args.size());
  43.277 +                super.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/String");
  43.278 +                boolean needsVM = false;
  43.279 +                for (int i = 0; i < args.size(); i++) {
  43.280 +                    assert !needsVM;
  43.281 +                    String argName = args.get(i);
  43.282 +                    needsVM = "vm".equals(argName);
  43.283 +                    super.visitInsn(Opcodes.DUP);
  43.284 +                    super.visitIntInsn(Opcodes.BIPUSH, i);
  43.285 +                    super.visitLdcInsn(argName);
  43.286 +                    super.visitInsn(Opcodes.AASTORE);
  43.287 +                }
  43.288 +                super.visitMethodInsn(Opcodes.INVOKESTATIC,
  43.289 +                        "org/apidesign/html/boot/spi/Fn", "define",
  43.290 +                        "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/String;)Lorg/apidesign/html/boot/spi/Fn;"
  43.291 +                );
  43.292 +                if (resource != null) {
  43.293 +                    super.visitLdcInsn(Type.getObjectType(FindInClass.this.name));
  43.294 +                    super.visitLdcInsn(resource);
  43.295 +                    super.visitMethodInsn(Opcodes.INVOKESTATIC,
  43.296 +                            "org/apidesign/html/boot/spi/Fn", "preload",
  43.297 +                            "(Lorg/apidesign/html/boot/spi/Fn;Ljava/lang/Class;Ljava/lang/String;)Lorg/apidesign/html/boot/spi/Fn;"
  43.298 +                    );
  43.299 +                }
  43.300 +                super.visitInsn(Opcodes.DUP);
  43.301 +                super.visitFieldInsn(
  43.302 +                        Opcodes.PUTSTATIC, FindInClass.this.name,
  43.303 +                        "$$fn$$" + name + "_" + found,
  43.304 +                        "Lorg/apidesign/html/boot/spi/Fn;"
  43.305 +                );
  43.306 +                // end of Fn init
  43.307 +
  43.308 +                super.visitLabel(ifNotNull);
  43.309 +
  43.310 +                final int offset;
  43.311 +                if ((access & Opcodes.ACC_STATIC) == 0) {
  43.312 +                    offset = 1;
  43.313 +                    super.visitIntInsn(Opcodes.ALOAD, 0);
  43.314 +                } else {
  43.315 +                    offset = 0;
  43.316 +                    super.visitInsn(Opcodes.ACONST_NULL);
  43.317 +                }
  43.318 +
  43.319 +                super.visitIntInsn(Opcodes.SIPUSH, args.size());
  43.320 +                super.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
  43.321 +
  43.322 +                class SV extends SignatureVisitor {
  43.323 +
  43.324 +                    private boolean nowReturn;
  43.325 +                    private Type returnType;
  43.326 +                    private int index;
  43.327 +                    private int loadIndex = offset;
  43.328 +
  43.329 +                    public SV() {
  43.330 +                        super(Opcodes.ASM4);
  43.331 +                    }
  43.332 +
  43.333 +                    @Override
  43.334 +                    public void visitBaseType(char descriptor) {
  43.335 +                        final Type t = Type.getType("" + descriptor);
  43.336 +                        if (nowReturn) {
  43.337 +                            returnType = t;
  43.338 +                            return;
  43.339 +                        }
  43.340 +                        FindInMethod.super.visitInsn(Opcodes.DUP);
  43.341 +                        FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, index++);
  43.342 +                        FindInMethod.super.visitVarInsn(t.getOpcode(Opcodes.ILOAD), loadIndex++);
  43.343 +                        String factory;
  43.344 +                        switch (descriptor) {
  43.345 +                            case 'I':
  43.346 +                                factory = "java/lang/Integer";
  43.347 +                                break;
  43.348 +                            case 'J':
  43.349 +                                factory = "java/lang/Long";
  43.350 +                                loadIndex++;
  43.351 +                                break;
  43.352 +                            case 'S':
  43.353 +                                factory = "java/lang/Short";
  43.354 +                                break;
  43.355 +                            case 'F':
  43.356 +                                factory = "java/lang/Float";
  43.357 +                                break;
  43.358 +                            case 'D':
  43.359 +                                factory = "java/lang/Double";
  43.360 +                                loadIndex++;
  43.361 +                                break;
  43.362 +                            case 'Z':
  43.363 +                                factory = "java/lang/Boolean";
  43.364 +                                break;
  43.365 +                            case 'C':
  43.366 +                                factory = "java/lang/Character";
  43.367 +                                break;
  43.368 +                            case 'B':
  43.369 +                                factory = "java/lang/Byte";
  43.370 +                                break;
  43.371 +                            default:
  43.372 +                                throw new IllegalStateException(t.toString());
  43.373 +                        }
  43.374 +                        FindInMethod.super.visitMethodInsn(Opcodes.INVOKESTATIC,
  43.375 +                                factory, "valueOf", "(" + descriptor + ")L" + factory + ";"
  43.376 +                        );
  43.377 +                        FindInMethod.super.visitInsn(Opcodes.AASTORE);
  43.378 +                    }
  43.379 +
  43.380 +                    @Override
  43.381 +                    public SignatureVisitor visitArrayType() {
  43.382 +                        if (nowReturn) {
  43.383 +                            throw new IllegalStateException("Not supported yet");
  43.384 +                        }
  43.385 +                        loadObject();
  43.386 +                        return new SignatureWriter();
  43.387 +                    }
  43.388 +
  43.389 +                    @Override
  43.390 +                    public void visitClassType(String name) {
  43.391 +                        if (nowReturn) {
  43.392 +                            returnType = Type.getObjectType(name);
  43.393 +                            return;
  43.394 +                        }
  43.395 +                        loadObject();
  43.396 +                    }
  43.397 +
  43.398 +                    @Override
  43.399 +                    public SignatureVisitor visitReturnType() {
  43.400 +                        nowReturn = true;
  43.401 +                        return this;
  43.402 +                    }
  43.403 +
  43.404 +                    private void loadObject() {
  43.405 +                        FindInMethod.super.visitInsn(Opcodes.DUP);
  43.406 +                        FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, index++);
  43.407 +                        FindInMethod.super.visitVarInsn(Opcodes.ALOAD, loadIndex++);
  43.408 +                        FindInMethod.super.visitInsn(Opcodes.AASTORE);
  43.409 +                    }
  43.410 +
  43.411 +                }
  43.412 +                SV sv = new SV();
  43.413 +                SignatureReader sr = new SignatureReader(desc);
  43.414 +                sr.accept(sv);
  43.415 +
  43.416 +                if (needsVM) {
  43.417 +                    FindInMethod.super.visitInsn(Opcodes.DUP);
  43.418 +                    FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, sv.index);
  43.419 +                    int lastSlash = FindInClass.this.name.lastIndexOf('/');
  43.420 +                    String jsCallbacks = FindInClass.this.name.substring(0, lastSlash + 1) + "$JsCallbacks$";
  43.421 +                    FindInMethod.super.visitFieldInsn(Opcodes.GETSTATIC, jsCallbacks, "VM", "L" + jsCallbacks + ";");
  43.422 +                    FindInMethod.super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, jsCallbacks, "current", "()L" + jsCallbacks + ";");
  43.423 +                    FindInMethod.super.visitInsn(Opcodes.AASTORE);
  43.424 +                }
  43.425 +
  43.426 +                super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
  43.427 +                        "org/apidesign/html/boot/spi/Fn", "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"
  43.428 +                );
  43.429 +                switch (sv.returnType.getSort()) {
  43.430 +                    case Type.VOID:
  43.431 +                        super.visitInsn(Opcodes.RETURN);
  43.432 +                        break;
  43.433 +                    case Type.ARRAY:
  43.434 +                    case Type.OBJECT:
  43.435 +                        super.visitTypeInsn(Opcodes.CHECKCAST, sv.returnType.getInternalName());
  43.436 +                        super.visitInsn(Opcodes.ARETURN);
  43.437 +                        break;
  43.438 +                    case Type.BOOLEAN:
  43.439 +                        super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Boolean");
  43.440 +                        super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
  43.441 +                                "java/lang/Boolean", "booleanValue", "()Z"
  43.442 +                        );
  43.443 +                        super.visitInsn(Opcodes.IRETURN);
  43.444 +                        break;
  43.445 +                    default:
  43.446 +                        super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Number");
  43.447 +                        super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
  43.448 +                                "java/lang/Number", sv.returnType.getClassName() + "Value", "()" + sv.returnType.getDescriptor()
  43.449 +                        );
  43.450 +                        super.visitInsn(sv.returnType.getOpcode(Opcodes.IRETURN));
  43.451 +                }
  43.452 +                return true;
  43.453 +            }
  43.454 +
  43.455 +            @Override
  43.456 +            public void visitEnd() {
  43.457 +                super.visitEnd();
  43.458 +                if (body != null) {
  43.459 +                    if (generateBody()) {
  43.460 +                        // native method
  43.461 +                        super.visitMaxs(1, 0);
  43.462 +                    }
  43.463 +                    FindInClass.this.visitField(
  43.464 +                            Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
  43.465 +                            "$$fn$$" + name + "_" + found,
  43.466 +                            "Lorg/apidesign/html/boot/spi/Fn;",
  43.467 +                            null, null
  43.468 +                    );
  43.469 +                }
  43.470 +            }
  43.471 +
  43.472 +            private final class FindInAnno extends AnnotationVisitor {
  43.473 +
  43.474 +                private List<String> args = new ArrayList<String>();
  43.475 +                private String body;
  43.476 +                private boolean javacall = false;
  43.477 +
  43.478 +                public FindInAnno() {
  43.479 +                    super(Opcodes.ASM4);
  43.480 +                }
  43.481 +
  43.482 +                @Override
  43.483 +                public void visit(String name, Object value) {
  43.484 +                    if (name == null) {
  43.485 +                        args.add((String) value);
  43.486 +                        return;
  43.487 +                    }
  43.488 +                    if (name.equals("javacall")) { // NOI18N
  43.489 +                        javacall = (Boolean) value;
  43.490 +                        return;
  43.491 +                    }
  43.492 +                    assert name.equals("body");
  43.493 +                    body = (String) value;
  43.494 +                }
  43.495 +
  43.496 +                @Override
  43.497 +                public AnnotationVisitor visitArray(String name) {
  43.498 +                    return this;
  43.499 +                }
  43.500 +
  43.501 +                @Override
  43.502 +                public void visitEnd() {
  43.503 +                    if (body != null) {
  43.504 +                        if (javacall) {
  43.505 +                            body = callback(body);
  43.506 +                            args.add("vm");
  43.507 +                        }
  43.508 +                        generateJSBody(args, body);
  43.509 +                    }
  43.510 +                }
  43.511 +            }
  43.512 +        }
  43.513 +
  43.514 +        private final class LoadResource extends AnnotationVisitor {
  43.515 +
  43.516 +            public LoadResource() {
  43.517 +                super(Opcodes.ASM4);
  43.518 +            }
  43.519 +
  43.520 +            @Override
  43.521 +            public void visit(String attrName, Object value) {
  43.522 +                String relPath = (String) value;
  43.523 +                if (relPath.startsWith("/")) {
  43.524 +                    resource = relPath;
  43.525 +                } else {
  43.526 +                    int last = name.lastIndexOf('/');
  43.527 +                    String fullPath = name.substring(0, last + 1) + relPath;
  43.528 +                    resource = fullPath;
  43.529 +                }
  43.530 +            }
  43.531 +        }
  43.532 +    }
  43.533 +
  43.534 +    private static class ClassWriterEx extends ClassWriter {
  43.535 +
  43.536 +        private ClassLoader loader;
  43.537 +
  43.538 +        public ClassWriterEx(ClassLoader l, ClassReader classReader, int flags) {
  43.539 +            super(classReader, flags);
  43.540 +            this.loader = l;
  43.541 +        }
  43.542 +
  43.543 +        @Override
  43.544 +        protected String getCommonSuperClass(final String type1, final String type2) {
  43.545 +            Class<?> c, d;
  43.546 +            try {
  43.547 +                c = Class.forName(type1.replace('/', '.'), false, loader);
  43.548 +                d = Class.forName(type2.replace('/', '.'), false, loader);
  43.549 +            } catch (Exception e) {
  43.550 +                throw new RuntimeException(e.toString());
  43.551 +            }
  43.552 +            if (c.isAssignableFrom(d)) {
  43.553 +                return type1;
  43.554 +            }
  43.555 +            if (d.isAssignableFrom(c)) {
  43.556 +                return type2;
  43.557 +            }
  43.558 +            if (c.isInterface() || d.isInterface()) {
  43.559 +                return "java/lang/Object";
  43.560 +            } else {
  43.561 +                do {
  43.562 +                    c = c.getSuperclass();
  43.563 +                } while (!c.isAssignableFrom(d));
  43.564 +                return c.getName().replace('.', '/');
  43.565 +            }
  43.566 +        }
  43.567 +    }
  43.568 +
  43.569 +    static byte[] transform(ClassLoader loader, byte[] arr) {
  43.570 +        ClassReader cr = new ClassReader(arr) {
  43.571 +            // to allow us to compile with -profile compact1 on 
  43.572 +            // JDK8 while processing the class as JDK7, the highest
  43.573 +            // class format asm 4.1 understands to
  43.574 +            @Override
  43.575 +            public short readShort(int index) {
  43.576 +                short s = super.readShort(index);
  43.577 +                if (index == 6 && s > Opcodes.V1_7) {
  43.578 +                    return Opcodes.V1_7;
  43.579 +                }
  43.580 +                return s;
  43.581 +            }
  43.582 +        };
  43.583 +        FindInClass tst = new FindInClass(loader, null);
  43.584 +        cr.accept(tst, 0);
  43.585 +        if (tst.found > 0) {
  43.586 +            ClassWriter w = new ClassWriterEx(loader, cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
  43.587 +            FindInClass fic = new FindInClass(loader, w);
  43.588 +            cr.accept(fic, 0);
  43.589 +            arr = w.toByteArray();
  43.590 +        }
  43.591 +        return arr;
  43.592 +    }
  43.593 +
  43.594 +    private static final class TrueFn extends Fn {
  43.595 +        @Override
  43.596 +        public Object invoke(Object thiz, Object... args) throws Exception {
  43.597 +            return Boolean.TRUE;
  43.598 +        }
  43.599 +    } // end of TrueFn
  43.600 +}
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/JavaScriptProcesor.java	Mon Dec 16 17:16:40 2013 +0100
    44.3 @@ -0,0 +1,369 @@
    44.4 +/**
    44.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    44.6 + *
    44.7 + * Copyright 1997-2010 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.IOException;
   44.49 +import java.io.Writer;
   44.50 +import java.util.Collections;
   44.51 +import java.util.HashMap;
   44.52 +import java.util.HashSet;
   44.53 +import java.util.List;
   44.54 +import java.util.Map;
   44.55 +import java.util.Set;
   44.56 +import java.util.TreeMap;
   44.57 +import javax.annotation.processing.AbstractProcessor;
   44.58 +import javax.annotation.processing.Completion;
   44.59 +import javax.annotation.processing.Completions;
   44.60 +import javax.annotation.processing.Messager;
   44.61 +import javax.annotation.processing.Processor;
   44.62 +import javax.annotation.processing.RoundEnvironment;
   44.63 +import javax.lang.model.SourceVersion;
   44.64 +import javax.lang.model.element.AnnotationMirror;
   44.65 +import javax.lang.model.element.Element;
   44.66 +import javax.lang.model.element.ElementKind;
   44.67 +import javax.lang.model.element.ExecutableElement;
   44.68 +import javax.lang.model.element.Modifier;
   44.69 +import javax.lang.model.element.PackageElement;
   44.70 +import javax.lang.model.element.TypeElement;
   44.71 +import javax.lang.model.element.VariableElement;
   44.72 +import javax.lang.model.type.ArrayType;
   44.73 +import javax.lang.model.type.ExecutableType;
   44.74 +import javax.lang.model.type.TypeKind;
   44.75 +import javax.lang.model.type.TypeMirror;
   44.76 +import javax.tools.Diagnostic;
   44.77 +import javax.tools.FileObject;
   44.78 +import javax.tools.StandardLocation;
   44.79 +import net.java.html.js.JavaScriptBody;
   44.80 +import net.java.html.js.JavaScriptResource;
   44.81 +import org.openide.util.lookup.ServiceProvider;
   44.82 +
   44.83 +/**
   44.84 + *
   44.85 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   44.86 + */
   44.87 +@ServiceProvider(service = Processor.class)
   44.88 +public final class JavaScriptProcesor extends AbstractProcessor {
   44.89 +    private final Map<String,Map<String,ExecutableElement>> javacalls = 
   44.90 +        new HashMap<String,Map<String,ExecutableElement>>();
   44.91 +    
   44.92 +    @Override
   44.93 +    public Set<String> getSupportedAnnotationTypes() {
   44.94 +        Set<String> set = new HashSet<String>();
   44.95 +        set.add(JavaScriptBody.class.getName());
   44.96 +        set.add(JavaScriptResource.class.getName());
   44.97 +        return set;
   44.98 +    }
   44.99 +    
  44.100 +    @Override
  44.101 +    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
  44.102 +        final Messager msg = processingEnv.getMessager();
  44.103 +        for (Element e : roundEnv.getElementsAnnotatedWith(JavaScriptBody.class)) {
  44.104 +            if (e.getKind() != ElementKind.METHOD && e.getKind() != ElementKind.CONSTRUCTOR) {
  44.105 +                continue;
  44.106 +            }
  44.107 +            ExecutableElement ee = (ExecutableElement)e;
  44.108 +            List<? extends VariableElement> params = ee.getParameters();
  44.109 +            
  44.110 +            JavaScriptBody jsb = e.getAnnotation(JavaScriptBody.class);
  44.111 +            if (jsb == null) {
  44.112 +                continue;
  44.113 +            }
  44.114 +            String[] arr = jsb.args();
  44.115 +            if (params.size() != arr.length) {
  44.116 +                msg.printMessage(Diagnostic.Kind.ERROR, "Number of args arguments does not match real arguments!", e);
  44.117 +            }
  44.118 +            if (!jsb.javacall() && jsb.body().contains(".@")) {
  44.119 +                msg.printMessage(Diagnostic.Kind.WARNING, "Usage of .@ usually requires javacall=true", e);
  44.120 +            }
  44.121 +            if (jsb.javacall()) {
  44.122 +                JsCallback verify = new VerifyCallback(e);
  44.123 +                try {
  44.124 +                    verify.parse(jsb.body());
  44.125 +                } catch (IllegalStateException ex) {
  44.126 +                    msg.printMessage(Diagnostic.Kind.ERROR, ex.getLocalizedMessage(), e);
  44.127 +                }
  44.128 +            }
  44.129 +        }
  44.130 +        for (Element e : roundEnv.getElementsAnnotatedWith(JavaScriptResource.class)) {
  44.131 +            JavaScriptResource r = e.getAnnotation(JavaScriptResource.class);
  44.132 +            if (r == null) {
  44.133 +                continue;
  44.134 +            }
  44.135 +            final String res;
  44.136 +            if (r.value().startsWith("/")) {
  44.137 +                res = r.value();
  44.138 +            } else {
  44.139 +                res = findPkg(e).replace('.', '/') + "/" + r.value();
  44.140 +            }
  44.141 +            
  44.142 +            try {
  44.143 +                FileObject os = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", res);
  44.144 +                os.openInputStream().close();
  44.145 +            } catch (IOException ex1) {
  44.146 +                try {
  44.147 +                    FileObject os2 = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", res);
  44.148 +                    os2.openInputStream().close();
  44.149 +                } catch (IOException ex2) {
  44.150 +                    msg.printMessage(Diagnostic.Kind.ERROR, "Cannot find " + res + " in " + res + " package", e);
  44.151 +                }
  44.152 +            }
  44.153 +        }
  44.154 +
  44.155 +        if (roundEnv.processingOver()) {
  44.156 +            generateCallbackClass(javacalls);
  44.157 +            javacalls.clear();
  44.158 +        }
  44.159 +        return true;
  44.160 +    }
  44.161 +
  44.162 +    @Override
  44.163 +    public Iterable<? extends Completion> getCompletions(Element e, 
  44.164 +        AnnotationMirror annotation, ExecutableElement member, String userText
  44.165 +    ) {
  44.166 +        StringBuilder sb = new StringBuilder();
  44.167 +        if (e.getKind() == ElementKind.METHOD && member.getSimpleName().contentEquals("args")) {
  44.168 +            ExecutableElement ee = (ExecutableElement) e;
  44.169 +            String sep = "";
  44.170 +            sb.append("{ ");
  44.171 +            for (VariableElement ve : ee.getParameters()) {
  44.172 +                sb.append(sep).append('"').append(ve.getSimpleName())
  44.173 +                    .append('"');
  44.174 +                sep = ", ";
  44.175 +            }
  44.176 +            sb.append(" }");
  44.177 +            return Collections.nCopies(1, Completions.of(sb.toString()));
  44.178 +        }
  44.179 +        return null;
  44.180 +    }
  44.181 +
  44.182 +    private class VerifyCallback extends JsCallback {
  44.183 +        private final Element e;
  44.184 +        public VerifyCallback(Element e) {
  44.185 +            this.e = e;
  44.186 +        }
  44.187 +
  44.188 +        @Override
  44.189 +        protected CharSequence callMethod(String ident, String fqn, String method, String params) {
  44.190 +            final TypeElement type = processingEnv.getElementUtils().getTypeElement(fqn);
  44.191 +            if (type == null) {
  44.192 +                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, 
  44.193 +                    "Callback to non-existing class " + fqn, e
  44.194 +                );
  44.195 +                return "";
  44.196 +            }
  44.197 +            ExecutableElement found = null;
  44.198 +            StringBuilder foundParams = new StringBuilder();
  44.199 +            for (Element m : type.getEnclosedElements()) {
  44.200 +                if (m.getKind() != ElementKind.METHOD) {
  44.201 +                    continue;
  44.202 +                }
  44.203 +                if (m.getSimpleName().contentEquals(method)) {
  44.204 +                    String paramTypes = findParamTypes((ExecutableElement)m);
  44.205 +                    if (paramTypes.equals(params)) {
  44.206 +                        found = (ExecutableElement) m;
  44.207 +                        break;
  44.208 +                    }
  44.209 +                    foundParams.append(paramTypes).append("\n");
  44.210 +                }
  44.211 +            }
  44.212 +            if (found == null) {
  44.213 +                if (foundParams.length() == 0) {
  44.214 +                    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, 
  44.215 +                        "Callback to class " + fqn + " with unknown method " + method, e
  44.216 +                    );
  44.217 +                } else {
  44.218 +                    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, 
  44.219 +                        "Callback to " + fqn + "." + method + " with wrong parameters: " + 
  44.220 +                        params + ". Only known parameters are " + foundParams, e
  44.221 +                    );
  44.222 +                }
  44.223 +            } else {
  44.224 +                Map<String,ExecutableElement> mangledOnes = javacalls.get(findPkg(e));
  44.225 +                if (mangledOnes == null) {
  44.226 +                    mangledOnes = new TreeMap<String, ExecutableElement>();
  44.227 +                    javacalls.put(findPkg(e), mangledOnes);
  44.228 +                }
  44.229 +                String mangled = JsCallback.mangle(fqn, method, findParamTypes(found));
  44.230 +                mangledOnes.put(mangled, found);
  44.231 +            }
  44.232 +            return "";
  44.233 +        }
  44.234 +
  44.235 +        private String findParamTypes(ExecutableElement method) {
  44.236 +            ExecutableType t = (ExecutableType) method.asType();
  44.237 +            StringBuilder sb = new StringBuilder();
  44.238 +            sb.append('(');
  44.239 +            for (TypeMirror tm : t.getParameterTypes()) {
  44.240 +                if (tm.getKind().isPrimitive()) {
  44.241 +                    switch (tm.getKind()) {
  44.242 +                        case INT: sb.append('I'); break;
  44.243 +                        case BOOLEAN: sb.append('Z'); break;
  44.244 +                        case BYTE: sb.append('B'); break;
  44.245 +                        case CHAR: sb.append('C'); break;
  44.246 +                        case SHORT: sb.append('S'); break;
  44.247 +                        case DOUBLE: sb.append('D'); break;
  44.248 +                        case FLOAT: sb.append('F'); break;
  44.249 +                        case LONG: sb.append('J'); break;
  44.250 +                        default:
  44.251 +                            throw new IllegalStateException("Uknown " + tm.getKind());
  44.252 +                    }
  44.253 +                } else {
  44.254 +                    while (tm.getKind() == TypeKind.ARRAY) {
  44.255 +                        sb.append('[');
  44.256 +                        tm = ((ArrayType)tm).getComponentType();
  44.257 +                    }
  44.258 +                    sb.append('L');
  44.259 +                    sb.append(tm.toString().replace('.', '/'));
  44.260 +                    sb.append(';');
  44.261 +                }
  44.262 +            }
  44.263 +            sb.append(')');
  44.264 +            return sb.toString();
  44.265 +        }
  44.266 +    }
  44.267 +    
  44.268 +    private void generateCallbackClass(Map<String,Map<String, ExecutableElement>> process) {
  44.269 +        for (Map.Entry<String, Map<String, ExecutableElement>> pkgEn : process.entrySet()) {
  44.270 +            String pkgName = pkgEn.getKey();
  44.271 +            Map<String, ExecutableElement> map = pkgEn.getValue();
  44.272 +            StringBuilder source = new StringBuilder();
  44.273 +            source.append("package ").append(pkgName).append(";\n");
  44.274 +            source.append("public final class $JsCallbacks$ {\n");
  44.275 +            source.append("  static final $JsCallbacks$ VM = new $JsCallbacks$(null);\n");
  44.276 +            source.append("  private final org.apidesign.html.boot.spi.Fn.Presenter p;\n");
  44.277 +            source.append("  private $JsCallbacks$ last;\n");
  44.278 +            source.append("  private $JsCallbacks$(org.apidesign.html.boot.spi.Fn.Presenter p) {\n");
  44.279 +            source.append("    this.p = p;\n");
  44.280 +            source.append("  }\n");
  44.281 +            source.append("  final $JsCallbacks$ current() {\n");
  44.282 +            source.append("    org.apidesign.html.boot.spi.Fn.Presenter now = org.apidesign.html.boot.spi.Fn.activePresenter();\n");
  44.283 +            source.append("    if (now == p) return this;\n");
  44.284 +            source.append("    if (last != null && now == last.p) return last;\n");
  44.285 +            source.append("    return last = new $JsCallbacks$(now);\n");
  44.286 +            source.append("  }\n");
  44.287 +            for (Map.Entry<String, ExecutableElement> entry : map.entrySet()) {
  44.288 +                final String mangled = entry.getKey();
  44.289 +                final ExecutableElement m = entry.getValue();
  44.290 +                final boolean isStatic = m.getModifiers().contains(Modifier.STATIC);
  44.291 +                
  44.292 +                source.append("\n  public java.lang.Object ")
  44.293 +                    .append(mangled)
  44.294 +                    .append("(");
  44.295 +                
  44.296 +                String sep = "";
  44.297 +                if (!isStatic) {
  44.298 +                    source.append(((TypeElement)m.getEnclosingElement()).getQualifiedName());
  44.299 +                    source.append(" self");
  44.300 +                    sep = ", ";
  44.301 +                }
  44.302 +                
  44.303 +                int cnt = 0;
  44.304 +                for (VariableElement ve : m.getParameters()) {
  44.305 +                    source.append(sep);
  44.306 +                    source.append(ve.asType());
  44.307 +                    source.append(" arg").append(++cnt);
  44.308 +                    sep = ", ";
  44.309 +                }
  44.310 +                source.append(") throws Throwable {\n");
  44.311 +                if (processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_7) >= 0) {
  44.312 +                    source.append("    try (java.io.Closeable a = org.apidesign.html.boot.spi.Fn.activate(p)) { \n");
  44.313 +                } else {
  44.314 +                    source.append("    java.io.Closeable a = org.apidesign.html.boot.spi.Fn.activate(p); try {\n");
  44.315 +                }
  44.316 +                source.append("    ");
  44.317 +                if (m.getReturnType().getKind() != TypeKind.VOID) {
  44.318 +                    source.append("return ");
  44.319 +                }
  44.320 +                if (isStatic) {
  44.321 +                    source.append(((TypeElement)m.getEnclosingElement()).getQualifiedName());
  44.322 +                    source.append('.');
  44.323 +                } else {
  44.324 +                    source.append("self.");
  44.325 +                }
  44.326 +                source.append(m.getSimpleName());
  44.327 +                source.append("(");
  44.328 +                cnt = 0;
  44.329 +                sep = "";
  44.330 +                for (VariableElement ve : m.getParameters()) {
  44.331 +                    source.append(sep);
  44.332 +                    source.append("arg").append(++cnt);
  44.333 +                    sep = ", ";
  44.334 +                }
  44.335 +                source.append(");\n");
  44.336 +                if (m.getReturnType().getKind() == TypeKind.VOID) {
  44.337 +                    source.append("    return null;\n");
  44.338 +                }
  44.339 +                if (processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_7) >= 0) {
  44.340 +                    source.append("    }\n");
  44.341 +                } else {
  44.342 +                    
  44.343 +                    source.append("    } finally {\n");
  44.344 +                    source.append("      a.close();\n");
  44.345 +                    source.append("    }\n");
  44.346 +                }
  44.347 +                source.append("  }\n");
  44.348 +            }
  44.349 +            source.append("}\n");
  44.350 +            final String srcName = pkgName + ".$JsCallbacks$";
  44.351 +            try {
  44.352 +                Writer w = processingEnv.getFiler().createSourceFile(srcName,
  44.353 +                    map.values().toArray(new Element[map.size()])
  44.354 +                ).openWriter();
  44.355 +                w.write(source.toString());
  44.356 +                w.close();
  44.357 +            } catch (IOException ex) {
  44.358 +                processingEnv.getMessager().printMessage(
  44.359 +                    Diagnostic.Kind.ERROR, "Can't write " + srcName + ": " + ex.getMessage()
  44.360 +                );
  44.361 +            }
  44.362 +        }
  44.363 +    }
  44.364 +    
  44.365 +    private static String findPkg(Element e) {
  44.366 +        while (e.getKind() != ElementKind.PACKAGE) {
  44.367 +            e = e.getEnclosingElement();
  44.368 +        }
  44.369 +        return ((PackageElement)e).getQualifiedName().toString();
  44.370 +    }
  44.371 +    
  44.372 +}
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/JsAgent.java	Mon Dec 16 17:16:40 2013 +0100
    45.3 @@ -0,0 +1,67 @@
    45.4 +/**
    45.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    45.6 + *
    45.7 + * Copyright 1997-2010 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.lang.instrument.ClassFileTransformer;
   45.49 +import java.lang.instrument.IllegalClassFormatException;
   45.50 +import java.lang.instrument.Instrumentation;
   45.51 +import java.security.ProtectionDomain;
   45.52 +
   45.53 +/**
   45.54 + *
   45.55 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   45.56 + */
   45.57 +public final class JsAgent implements ClassFileTransformer {
   45.58 +    public static void agentmain(String args, Instrumentation instr) {
   45.59 +        instr.addTransformer(new JsAgent());
   45.60 +    }
   45.61 +
   45.62 +    @Override
   45.63 +    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
   45.64 +        try {
   45.65 +            return FnUtils.transform(loader, classfileBuffer);
   45.66 +        } catch (Exception ex) {
   45.67 +            return classfileBuffer;
   45.68 +        }
   45.69 +    }
   45.70 +}
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/JsCallback.java	Mon Dec 16 17:16:40 2013 +0100
    46.3 @@ -0,0 +1,160 @@
    46.4 +/**
    46.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    46.6 + *
    46.7 + * Copyright 1997-2010 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 +
   46.49 +/**
   46.50 + *
   46.51 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   46.52 + */
   46.53 +abstract class JsCallback {
   46.54 +    final String parse(String body) {
   46.55 +        StringBuilder sb = new StringBuilder();
   46.56 +        int pos = 0;
   46.57 +        for (;;) {
   46.58 +            int next = body.indexOf(".@", pos);
   46.59 +            if (next == -1) {
   46.60 +                sb.append(body.substring(pos));
   46.61 +                body = sb.toString();
   46.62 +                break;
   46.63 +            }
   46.64 +            int ident = next;
   46.65 +            while (ident > 0) {
   46.66 +                if (!Character.isJavaIdentifierPart(body.charAt(--ident))) {
   46.67 +                    ident++;
   46.68 +                    break;
   46.69 +                }
   46.70 +            }
   46.71 +            String refId = body.substring(ident, next);
   46.72 +            
   46.73 +            sb.append(body.substring(pos, ident));
   46.74 +            
   46.75 +            int sigBeg = body.indexOf('(', next);
   46.76 +            int sigEnd = body.indexOf(')', sigBeg);
   46.77 +            int colon4 = body.indexOf("::", next);
   46.78 +            if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
   46.79 +                throw new IllegalStateException(
   46.80 +                    "Wrong format of instance callback. "
   46.81 +                    + "Should be: 'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n" 
   46.82 +                    + body
   46.83 +                );
   46.84 +            }
   46.85 +            String fqn = body.substring(next + 2, colon4);
   46.86 +            String method = body.substring(colon4 + 2, sigBeg);
   46.87 +            String params = body.substring(sigBeg, sigEnd + 1);
   46.88 +
   46.89 +            int paramBeg = body.indexOf('(', sigEnd + 1);
   46.90 +            if (paramBeg == -1) {
   46.91 +                throw new IllegalStateException(
   46.92 +                    "Wrong format of instance callback. "
   46.93 +                    + "Should be: 'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n" 
   46.94 +                    + body
   46.95 +                );
   46.96 +            }
   46.97 +            
   46.98 +            sb.append(callMethod(refId, fqn, method, params));
   46.99 +            if (body.charAt(paramBeg + 1) != (')')) {
  46.100 +                sb.append(",");
  46.101 +            }
  46.102 +            pos = paramBeg + 1;
  46.103 +        }
  46.104 +        pos = 0;
  46.105 +        sb = null;
  46.106 +        for (;;) {
  46.107 +            int next = body.indexOf("@", pos);
  46.108 +            if (next == -1) {
  46.109 +                if (sb == null) {
  46.110 +                    return body;
  46.111 +                }
  46.112 +                sb.append(body.substring(pos));
  46.113 +                return sb.toString();
  46.114 +            }
  46.115 +            if (sb == null) {
  46.116 +                sb = new StringBuilder();
  46.117 +            }
  46.118 +            
  46.119 +            sb.append(body.substring(pos, next));
  46.120 +            
  46.121 +            int sigBeg = body.indexOf('(', next);
  46.122 +            int sigEnd = body.indexOf(')', sigBeg);
  46.123 +            int colon4 = body.indexOf("::", next);
  46.124 +            if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
  46.125 +                throw new IllegalStateException(
  46.126 +                    "Wrong format of static callback. "
  46.127 +                    + "Should be: '@pkg.Class::staticMethod(Ljava/lang/Object;)(param)':\n" 
  46.128 +                    + body
  46.129 +                );
  46.130 +            }
  46.131 +            String fqn = body.substring(next + 1, colon4);
  46.132 +            String method = body.substring(colon4 + 2, sigBeg);
  46.133 +            String params = body.substring(sigBeg, sigEnd + 1);
  46.134 +
  46.135 +            int paramBeg = body.indexOf('(', sigEnd + 1);
  46.136 +            
  46.137 +            sb.append(callMethod(null, fqn, method, params));
  46.138 +            pos = paramBeg + 1;
  46.139 +        }
  46.140 +    }
  46.141 +
  46.142 +    protected abstract CharSequence callMethod(
  46.143 +        String ident, String fqn, String method, String params
  46.144 +    );
  46.145 +
  46.146 +    static String mangle(String fqn, String method, String params) {
  46.147 +        if (params.startsWith("(")) {
  46.148 +            params = params.substring(1);
  46.149 +        }
  46.150 +        if (params.endsWith(")")) {
  46.151 +            params = params.substring(0, params.length() - 1);
  46.152 +        }
  46.153 +        return 
  46.154 +            replace(fqn) + "$" + replace(method) + "$" + replace(params);
  46.155 +    }
  46.156 +    
  46.157 +    private static String replace(String orig) {
  46.158 +        return orig.replace("_", "_1").
  46.159 +            replace(";", "_2").
  46.160 +            replace("[", "_3").
  46.161 +            replace('.', '_').replace('/', '_');
  46.162 +    }
  46.163 +}
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/JsClassLoader.java	Mon Dec 16 17:16:40 2013 +0100
    47.3 @@ -0,0 +1,133 @@
    47.4 +/**
    47.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    47.6 + *
    47.7 + * Copyright 1997-2010 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 org.apidesign.html.boot.spi.Fn;
   47.49 +import java.io.IOException;
   47.50 +import java.io.InputStream;
   47.51 +import java.io.Reader;
   47.52 +import java.net.URL;
   47.53 +import java.util.Enumeration;
   47.54 +
   47.55 +/** 
   47.56 + *
   47.57 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   47.58 + */
   47.59 +abstract class JsClassLoader extends ClassLoader {
   47.60 +    JsClassLoader(ClassLoader parent) {
   47.61 +        super(parent);
   47.62 +        setDefaultAssertionStatus(JsClassLoader.class.desiredAssertionStatus());
   47.63 +    }
   47.64 +    
   47.65 +    @Override
   47.66 +    protected abstract URL findResource(String name);
   47.67 +    
   47.68 +    @Override
   47.69 +    protected abstract Enumeration<URL> findResources(String name);
   47.70 +
   47.71 +    @Override
   47.72 +    protected Class<?> findClass(String name) throws ClassNotFoundException {
   47.73 +        if (name.startsWith("javafx")) {
   47.74 +            return Class.forName(name);
   47.75 +        }
   47.76 +        if (name.startsWith("netscape")) {
   47.77 +            return Class.forName(name);
   47.78 +        }
   47.79 +        if (name.startsWith("com.sun")) {
   47.80 +            return Class.forName(name);
   47.81 +        }
   47.82 +        if (name.equals(JsClassLoader.class.getName())) {
   47.83 +            return JsClassLoader.class;
   47.84 +        }
   47.85 +        if (name.equals(Fn.class.getName())) {
   47.86 +            return Fn.class;
   47.87 +        }
   47.88 +        if (name.equals(Fn.Presenter.class.getName())) {
   47.89 +            return Fn.Presenter.class;
   47.90 +        }
   47.91 +        if (name.equals(FnUtils.class.getName())) {
   47.92 +            return FnUtils.class;
   47.93 +        }
   47.94 +        if (
   47.95 +            name.equals("org.apidesign.html.boot.spi.Fn") ||
   47.96 +            name.equals("org.netbeans.html.boot.impl.FnUtils") ||
   47.97 +            name.equals("org.netbeans.html.boot.impl.FnContext")
   47.98 +        ) {
   47.99 +            return Class.forName(name);
  47.100 +        }
  47.101 +        URL u = findResource(name.replace('.', '/') + ".class");
  47.102 +        if (u != null) {
  47.103 +            InputStream is = null;
  47.104 +            try {
  47.105 +                is = u.openStream();
  47.106 +                byte[] arr = new byte[is.available()];
  47.107 +                int len = 0;
  47.108 +                while (len < arr.length) {
  47.109 +                    int read = is.read(arr, len, arr.length - len);
  47.110 +                    if (read == -1) {
  47.111 +                        throw new IOException("Can't read " + u);
  47.112 +                    }
  47.113 +                    len += read;
  47.114 +                }
  47.115 +                is.close();
  47.116 +                is = null;
  47.117 +                arr = FnUtils.transform(JsClassLoader.this, arr);
  47.118 +                if (arr != null) {
  47.119 +                    return defineClass(name, arr, 0, arr.length);
  47.120 +                }
  47.121 +            } catch (IOException ex) {
  47.122 +                throw new ClassNotFoundException("Can't load " + name, ex);
  47.123 +            } finally {
  47.124 +                try {
  47.125 +                    if (is != null) is.close();
  47.126 +                } catch (IOException ex) {
  47.127 +                    throw new ClassNotFoundException(null, ex);
  47.128 +                }
  47.129 +            }
  47.130 +        }
  47.131 +        return super.findClass(name);
  47.132 +    }
  47.133 +    
  47.134 +    protected abstract Fn defineFn(String code, String... names);
  47.135 +    protected abstract void loadScript(Reader code) throws Exception;
  47.136 +}
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/Test.java	Mon Dec 16 17:16:40 2013 +0100
    48.3 @@ -0,0 +1,57 @@
    48.4 +/**
    48.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    48.6 + *
    48.7 + * Copyright 1997-2010 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 +import java.util.concurrent.Callable;
   48.49 +import net.java.html.js.JavaScriptBody;
   48.50 +
   48.51 +/**
   48.52 + *
   48.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   48.54 + */
   48.55 +public final class Test implements Callable<Boolean> {
   48.56 +    @Override @JavaScriptBody(args = {}, body = "return true;")
   48.57 +    public Boolean call() {
   48.58 +        return false;
   48.59 +    }
   48.60 +}
    49.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/Arithm.java	Mon Dec 16 17:16:02 2013 +0100
    49.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.3 @@ -1,31 +0,0 @@
    49.4 -/**
    49.5 - * HTML via Java(tm) Language Bindings
    49.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    49.7 - *
    49.8 - * This program is free software: you can redistribute it and/or modify
    49.9 - * it under the terms of the GNU General Public License as published by
   49.10 - * the Free Software Foundation, version 2 of the License.
   49.11 - *
   49.12 - * This program is distributed in the hope that it will be useful,
   49.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   49.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   49.15 - * GNU General Public License for more details. apidesign.org
   49.16 - * designates this particular file as subject to the
   49.17 - * "Classpath" exception as provided by apidesign.org
   49.18 - * in the License file that accompanied this code.
   49.19 - *
   49.20 - * You should have received a copy of the GNU General Public License
   49.21 - * along with this program. Look for COPYING file in the top folder.
   49.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   49.23 - */
   49.24 -package org.apidesign.html.boot.impl;
   49.25 -
   49.26 -/**
   49.27 - *
   49.28 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   49.29 - */
   49.30 -public class Arithm {
   49.31 -    public int sumTwo(int a, int b) {
   49.32 -        return a + b;
   49.33 -    }
   49.34 -}
    50.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/Compile.java	Mon Dec 16 17:16:02 2013 +0100
    50.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.3 @@ -1,269 +0,0 @@
    50.4 -/**
    50.5 - * HTML via Java(tm) Language Bindings
    50.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    50.7 - *
    50.8 - * This program is free software: you can redistribute it and/or modify
    50.9 - * it under the terms of the GNU General Public License as published by
   50.10 - * the Free Software Foundation, version 2 of the License.
   50.11 - *
   50.12 - * This program is distributed in the hope that it will be useful,
   50.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   50.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   50.15 - * GNU General Public License for more details. apidesign.org
   50.16 - * designates this particular file as subject to the
   50.17 - * "Classpath" exception as provided by apidesign.org
   50.18 - * in the License file that accompanied this code.
   50.19 - *
   50.20 - * You should have received a copy of the GNU General Public License
   50.21 - * along with this program. Look for COPYING file in the top folder.
   50.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   50.23 - */
   50.24 -package org.apidesign.html.boot.impl;
   50.25 -
   50.26 -import java.io.ByteArrayInputStream;
   50.27 -import java.io.ByteArrayOutputStream;
   50.28 -import java.io.IOException;
   50.29 -import java.io.InputStream;
   50.30 -import java.io.OutputStream;
   50.31 -import java.net.URI;
   50.32 -import java.net.URISyntaxException;
   50.33 -import java.util.ArrayList;
   50.34 -import java.util.Arrays;
   50.35 -import java.util.HashMap;
   50.36 -import java.util.List;
   50.37 -import java.util.Locale;
   50.38 -import java.util.Map;
   50.39 -import java.util.regex.Matcher;
   50.40 -import java.util.regex.Pattern;
   50.41 -import javax.tools.Diagnostic;
   50.42 -import javax.tools.DiagnosticListener;
   50.43 -import javax.tools.FileObject;
   50.44 -import javax.tools.ForwardingJavaFileManager;
   50.45 -import javax.tools.JavaFileManager;
   50.46 -import javax.tools.JavaFileObject;
   50.47 -import javax.tools.JavaFileObject.Kind;
   50.48 -import javax.tools.SimpleJavaFileObject;
   50.49 -import javax.tools.StandardJavaFileManager;
   50.50 -import javax.tools.StandardLocation;
   50.51 -import javax.tools.ToolProvider;
   50.52 -import static org.testng.Assert.assertTrue;
   50.53 -import static org.testng.Assert.assertFalse;
   50.54 -import static org.testng.Assert.fail;
   50.55 -
   50.56 -/**
   50.57 - *
   50.58 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   50.59 - */
   50.60 -final class Compile implements DiagnosticListener<JavaFileObject> {
   50.61 -    private final List<Diagnostic<? extends JavaFileObject>> errors = 
   50.62 -            new ArrayList<Diagnostic<? extends JavaFileObject>>();
   50.63 -    private final Map<String, byte[]> classes;
   50.64 -    private final String pkg;
   50.65 -    private final String cls;
   50.66 -    private final String html;
   50.67 -    private final String sourceLevel;
   50.68 -
   50.69 -    private Compile(String html, String code, String sl) throws IOException {
   50.70 -        this.pkg = findPkg(code);
   50.71 -        this.cls = findCls(code);
   50.72 -        this.html = html;
   50.73 -        this.sourceLevel = sl;
   50.74 -        classes = compile(html, code);
   50.75 -    }
   50.76 -
   50.77 -    /** Performs compilation of given HTML page and associated Java code
   50.78 -     */
   50.79 -    public static Compile create(String html, String code) throws IOException {
   50.80 -        return create(html, code, "1.7");
   50.81 -    }
   50.82 -    static Compile create(String html, String code, String sourceLevel) throws IOException {
   50.83 -        return new Compile(html, code, sourceLevel);
   50.84 -    }
   50.85 -    
   50.86 -    /** Checks for given class among compiled resources */
   50.87 -    public byte[] get(String res) {
   50.88 -        return classes.get(res);
   50.89 -    }
   50.90 -    
   50.91 -    /** Obtains errors created during compilation.
   50.92 -     */
   50.93 -    public List<Diagnostic<? extends JavaFileObject>> getErrors() {
   50.94 -        List<Diagnostic<? extends JavaFileObject>> err;
   50.95 -        err = new ArrayList<Diagnostic<? extends JavaFileObject>>();
   50.96 -        for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
   50.97 -            if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
   50.98 -                err.add(diagnostic);
   50.99 -            }
  50.100 -        }
  50.101 -        return err;
  50.102 -    }
  50.103 -    
  50.104 -    private Map<String, byte[]> compile(final String html, final String code) throws IOException {
  50.105 -        StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
  50.106 -
  50.107 -        final Map<String, ByteArrayOutputStream> class2BAOS;
  50.108 -        class2BAOS = new HashMap<String, ByteArrayOutputStream>();
  50.109 -
  50.110 -        JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
  50.111 -            @Override
  50.112 -            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  50.113 -                return code;
  50.114 -            }
  50.115 -        };
  50.116 -        final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
  50.117 -            @Override
  50.118 -            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  50.119 -                return html;
  50.120 -            }
  50.121 -
  50.122 -            @Override
  50.123 -            public InputStream openInputStream() throws IOException {
  50.124 -                return new ByteArrayInputStream(html.getBytes());
  50.125 -            }
  50.126 -        };
  50.127 -        
  50.128 -        final URI scratch;
  50.129 -        try {
  50.130 -            scratch = new URI("mem://mem3");
  50.131 -        } catch (URISyntaxException ex) {
  50.132 -            throw new IOException(ex);
  50.133 -        }
  50.134 -        
  50.135 -        JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
  50.136 -            @Override
  50.137 -            public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
  50.138 -                if (kind  == Kind.CLASS) {
  50.139 -                    final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
  50.140 -
  50.141 -                    class2BAOS.put(className.replace('.', '/') + ".class", buffer);
  50.142 -                    return new SimpleJavaFileObject(sibling.toUri(), kind) {
  50.143 -                        @Override
  50.144 -                        public OutputStream openOutputStream() throws IOException {
  50.145 -                            return buffer;
  50.146 -                        }
  50.147 -                    };
  50.148 -                }
  50.149 -                
  50.150 -                if (kind == Kind.SOURCE) {
  50.151 -                    final String n = className.replace('.', '/') + ".java";
  50.152 -                    final URI un;
  50.153 -                    try {
  50.154 -                        un = new URI("mem://" + n);
  50.155 -                    } catch (URISyntaxException ex) {
  50.156 -                        throw new IOException(ex);
  50.157 -                    }
  50.158 -                    return new VirtFO(un/*sibling.toUri()*/, kind, n);
  50.159 -                }
  50.160 -                
  50.161 -                throw new IllegalStateException();
  50.162 -            }
  50.163 -
  50.164 -            @Override
  50.165 -            public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
  50.166 -                if (location == StandardLocation.SOURCE_PATH) {
  50.167 -                    if (packageName.equals(pkg)) {
  50.168 -                        return htmlFile;
  50.169 -                    }
  50.170 -                }
  50.171 -                
  50.172 -                return null;
  50.173 -            }
  50.174 -
  50.175 -            @Override
  50.176 -            public boolean isSameFile(FileObject a, FileObject b) {
  50.177 -                if (a instanceof VirtFO && b instanceof VirtFO) {
  50.178 -                    return ((VirtFO)a).getName().equals(((VirtFO)b).getName());
  50.179 -                }
  50.180 -                
  50.181 -                return super.isSameFile(a, b);
  50.182 -            }
  50.183 -
  50.184 -            class VirtFO extends SimpleJavaFileObject {
  50.185 -
  50.186 -                private final String n;
  50.187 -
  50.188 -                public VirtFO(URI uri, Kind kind, String n) {
  50.189 -                    super(uri, kind);
  50.190 -                    this.n = n;
  50.191 -                }
  50.192 -                private final ByteArrayOutputStream data = new ByteArrayOutputStream();
  50.193 -
  50.194 -                @Override
  50.195 -                public OutputStream openOutputStream() throws IOException {
  50.196 -                    return data;
  50.197 -                }
  50.198 -
  50.199 -                @Override
  50.200 -                public String getName() {
  50.201 -                    return n;
  50.202 -                }
  50.203 -
  50.204 -                @Override
  50.205 -                public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  50.206 -                    data.close();
  50.207 -                    return new String(data.toByteArray());
  50.208 -                }
  50.209 -            }
  50.210 -        };
  50.211 -
  50.212 -        ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", sourceLevel, "-target", "1.7"), null, Arrays.asList(file)).call();
  50.213 -
  50.214 -        Map<String, byte[]> result = new HashMap<String, byte[]>();
  50.215 -
  50.216 -        for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
  50.217 -            result.put(e.getKey(), e.getValue().toByteArray());
  50.218 -        }
  50.219 -
  50.220 -        return result;
  50.221 -    }
  50.222 -
  50.223 -
  50.224 -    @Override
  50.225 -    public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
  50.226 -        errors.add(diagnostic);
  50.227 -    }
  50.228 -    private static String findPkg(String java) throws IOException {
  50.229 -        Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
  50.230 -        Matcher m = p.matcher(java);
  50.231 -        if (!m.find()) {
  50.232 -            throw new IOException("Can't find package declaration in the java file");
  50.233 -        }
  50.234 -        String pkg = m.group(1);
  50.235 -        return pkg;
  50.236 -    }
  50.237 -    private static String findCls(String java) throws IOException {
  50.238 -        Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
  50.239 -        Matcher m = p.matcher(java);
  50.240 -        if (!m.find()) {
  50.241 -            throw new IOException("Can't find package declaration in the java file");
  50.242 -        }
  50.243 -        String cls = m.group(1);
  50.244 -        return cls;
  50.245 -    }
  50.246 -
  50.247 -    String getHtml() {
  50.248 -        String fqn = "'" + pkg + '.' + cls + "'";
  50.249 -        return html.replace("'${fqn}'", fqn);
  50.250 -    }
  50.251 -    void assertErrors() {
  50.252 -        assertFalse(getErrors().isEmpty(), "There are supposed to be some errors");
  50.253 -    }
  50.254 -
  50.255 -    void assertError(String expMsg) {
  50.256 -        StringBuilder sb = new StringBuilder();
  50.257 -        sb.append("Can't find ").append(expMsg).append(" among:");
  50.258 -        for (Diagnostic<? extends JavaFileObject> e : errors) {
  50.259 -            String msg = e.getMessage(Locale.US);
  50.260 -            if (msg.contains(expMsg)) {
  50.261 -                return;
  50.262 -            }
  50.263 -            sb.append("\n");
  50.264 -            sb.append(msg);
  50.265 -        }
  50.266 -        fail(sb.toString());
  50.267 -    }
  50.268 -
  50.269 -    void assertNoErrors() {
  50.270 -        assertTrue(getErrors().isEmpty(), "No errors expected: " + getErrors());
  50.271 -    }
  50.272 -}
    51.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/FnTest.java	Mon Dec 16 17:16:02 2013 +0100
    51.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.3 @@ -1,127 +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 -
   51.25 -package org.apidesign.html.boot.impl;
   51.26 -
   51.27 -import java.io.Closeable;
   51.28 -import java.io.Reader;
   51.29 -import java.net.URL;
   51.30 -import java.net.URLClassLoader;
   51.31 -import java.util.ArrayList;
   51.32 -import java.util.Arrays;
   51.33 -import java.util.Collection;
   51.34 -import java.util.List;
   51.35 -import javax.script.Invocable;
   51.36 -import javax.script.ScriptEngine;
   51.37 -import javax.script.ScriptEngineManager;
   51.38 -import javax.script.ScriptException;
   51.39 -import org.apidesign.html.boot.spi.Fn;
   51.40 -import org.testng.annotations.BeforeClass;
   51.41 -import org.testng.annotations.BeforeMethod;
   51.42 -
   51.43 -/**
   51.44 - *
   51.45 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   51.46 - */
   51.47 -public class FnTest extends JsClassLoaderBase {
   51.48 -    private static Fn.Presenter presenter;
   51.49 -    
   51.50 -    public FnTest() {
   51.51 -    }
   51.52 -
   51.53 -    @BeforeClass
   51.54 -    public static void createClassLoader() throws Exception {
   51.55 -        ScriptEngineManager sem = new ScriptEngineManager();
   51.56 -        final ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
   51.57 -        
   51.58 -        final URL my = FnTest.class.getProtectionDomain().getCodeSource().getLocation();
   51.59 -        ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
   51.60 -        final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
   51.61 -        
   51.62 -        class Impl implements FindResources, Fn.Presenter {
   51.63 -            @Override
   51.64 -            public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough) {
   51.65 -                URL u = ul.findResource(path);
   51.66 -                if (u != null) {
   51.67 -                    results.add(u);
   51.68 -                }
   51.69 -            }
   51.70 -
   51.71 -            @Override
   51.72 -            public Fn defineFn(String code, String... names) {
   51.73 -                StringBuilder sb = new StringBuilder();
   51.74 -                sb.append("(function() {");
   51.75 -                sb.append("return function(");
   51.76 -                String sep = "";
   51.77 -                for (String n : names) {
   51.78 -                    sb.append(sep);
   51.79 -                    sb.append(n);
   51.80 -                    sep = ", ";
   51.81 -                }
   51.82 -                sb.append(") {");
   51.83 -                sb.append(code);
   51.84 -                sb.append("};");
   51.85 -                sb.append("})()");
   51.86 -                try {
   51.87 -                    final Object val = eng.eval(sb.toString());
   51.88 -                    return new Fn(this) {
   51.89 -                        @Override
   51.90 -                        public Object invoke(Object thiz, Object... args) throws Exception {
   51.91 -                            List<Object> all = new ArrayList<Object>(args.length + 1);
   51.92 -                            all.add(thiz == null ? val : thiz);
   51.93 -                            all.addAll(Arrays.asList(args));
   51.94 -                            Invocable inv = (Invocable)eng;
   51.95 -                            try {
   51.96 -                                Object ret = inv.invokeMethod(val, "call", all.toArray());
   51.97 -                                return val.equals(ret) ? null : ret;
   51.98 -                            } catch (ScriptException ex) {
   51.99 -                                throw ex;
  51.100 -                            }
  51.101 -                        }
  51.102 -                    };
  51.103 -                } catch (ScriptException ex) {
  51.104 -                    throw new LinkageError("Can't parse: " + sb, ex);
  51.105 -                }
  51.106 -            }
  51.107 -
  51.108 -            @Override
  51.109 -            public void displayPage(URL resource, Runnable r) {
  51.110 -                throw new UnsupportedOperationException();
  51.111 -            }
  51.112 -
  51.113 -            @Override
  51.114 -            public void loadScript(Reader code) throws Exception {
  51.115 -                eng.eval(code);
  51.116 -            }
  51.117 -        }
  51.118 -        Impl impl = new Impl();
  51.119 -        ClassLoader loader = FnUtils.newLoader(impl, impl, parent);
  51.120 -        presenter = impl;
  51.121 -        
  51.122 -        Closeable close = FnContext.activate(impl);
  51.123 -        methodClass = loader.loadClass(JsMethods.class.getName());
  51.124 -        close.close();
  51.125 -    }
  51.126 -
  51.127 -    @BeforeMethod public void initPresenter() {
  51.128 -        FnContext.currentPresenter(presenter);
  51.129 -    }
  51.130 -}
    52.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JavaScriptProcesorTest.java	Mon Dec 16 17:16:02 2013 +0100
    52.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.3 @@ -1,107 +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.IOException;
   52.27 -import java.lang.reflect.Field;
   52.28 -import java.lang.reflect.Method;
   52.29 -import static org.testng.Assert.assertEquals;
   52.30 -import static org.testng.Assert.assertTrue;
   52.31 -import org.testng.annotations.Test;
   52.32 -
   52.33 -/**
   52.34 - *
   52.35 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   52.36 - */
   52.37 -public class JavaScriptProcesorTest {
   52.38 -    
   52.39 -    @Test public void detectCallbackToNonExistingClass() throws IOException {
   52.40 -        String code = "package x.y.z;\n"
   52.41 -            + "import net.java.html.js.JavaScriptBody;\n"
   52.42 -            + "class X {\n"
   52.43 -            + "  @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
   52.44 -            + "    \"r.@java.lang.Runable::run()();\"\n" // typo
   52.45 -            + "  )\n"
   52.46 -            + "  private static native void callback(Runnable r);\n"
   52.47 -            + "}\n";
   52.48 -        
   52.49 -        Compile c = Compile.create("", code);
   52.50 -        c.assertErrors();
   52.51 -        c.assertError("java.lang.Runable"); // typo
   52.52 -    }
   52.53 -
   52.54 -    @Test public void detectCallbackToNonExistingMethod() throws IOException {
   52.55 -        String code = "package x.y.z;\n"
   52.56 -            + "import net.java.html.js.JavaScriptBody;\n"
   52.57 -            + "class X {\n"
   52.58 -            + "  @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
   52.59 -            + "    \"r.@java.lang.Runnable::cancel()();\"\n"
   52.60 -            + "  )\n"
   52.61 -            + "  private static native void callback(Runnable r);\n"
   52.62 -            + "}\n";
   52.63 -        
   52.64 -        Compile c = Compile.create("", code);
   52.65 -        c.assertErrors();
   52.66 -        c.assertError("method cancel");
   52.67 -    }
   52.68 -
   52.69 -    @Test public void detectCallbackToNonExistingParams() throws IOException {
   52.70 -        String code = "package x.y.z;\n"
   52.71 -            + "import net.java.html.js.JavaScriptBody;\n"
   52.72 -            + "class X {\n"
   52.73 -            + "  @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
   52.74 -            + "    \"r.@java.lang.Runnable::run(I)(10);\"\n"
   52.75 -            + "  )\n"
   52.76 -            + "  private static native void callback(Runnable r);\n"
   52.77 -            + "}\n";
   52.78 -        
   52.79 -        Compile c = Compile.create("", code);
   52.80 -        c.assertErrors();
   52.81 -        c.assertError("wrong parameters: (I)");
   52.82 -    }
   52.83 -
   52.84 -    @Test public void objectTypeParamsAreOK() throws IOException {
   52.85 -        String code = "package x.y.z;\n"
   52.86 -            + "import net.java.html.js.JavaScriptBody;\n"
   52.87 -            + "class X {\n"
   52.88 -            + "  @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
   52.89 -            + "    \"r.@java.lang.Object::equals(Ljava/lang/Object;)(null);\"\n"
   52.90 -            + "  )\n"
   52.91 -            + "  private static native void testEqual(Object r);\n"
   52.92 -            + "}\n";
   52.93 -        
   52.94 -        Compile c = Compile.create("", code);
   52.95 -        c.assertNoErrors();
   52.96 -    }
   52.97 -    
   52.98 -    @Test public void generatesCallbacksThatReturnObject() throws Exception {
   52.99 -        Class<?> callbacksForTestPkg = Class.forName("org.apidesign.html.boot.impl.$JsCallbacks$");
  52.100 -        Method m = callbacksForTestPkg.getDeclaredMethod("java_lang_Runnable$run$", Runnable.class);
  52.101 -        assertEquals(m.getReturnType(), Object.class, "All methods always return object");
  52.102 -    }
  52.103 -    
  52.104 -    @Test public void hasInstanceField() throws Exception {
  52.105 -        Class<?> callbacksForTestPkg = Class.forName("org.apidesign.html.boot.impl.$JsCallbacks$");
  52.106 -        Field f = callbacksForTestPkg.getDeclaredField("VM");
  52.107 -        f.setAccessible(true);
  52.108 -        assertTrue(callbacksForTestPkg.isInstance(f.get(null)), "Singleton field VM");
  52.109 -    }
  52.110 -}
    53.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JsClassLoaderBase.java	Mon Dec 16 17:16:02 2013 +0100
    53.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.3 @@ -1,179 +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 -package org.apidesign.html.boot.impl;
   53.25 -
   53.26 -import java.lang.reflect.InvocationTargetException;
   53.27 -import java.lang.reflect.Method;
   53.28 -import java.lang.reflect.Modifier;
   53.29 -import static org.testng.Assert.*;
   53.30 -import org.testng.annotations.BeforeMethod;
   53.31 -import org.testng.annotations.Test;
   53.32 -
   53.33 -/**
   53.34 - *
   53.35 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   53.36 - */
   53.37 -public class JsClassLoaderBase {
   53.38 -    protected static Class<?> methodClass;
   53.39 -    
   53.40 -    public JsClassLoaderBase() {
   53.41 -    }
   53.42 -    
   53.43 -    @BeforeMethod
   53.44 -    public void assertClassDefined() {
   53.45 -        assertNotNull(methodClass, "BeforeClass set up code should provide methodClass");
   53.46 -    }
   53.47 -
   53.48 -    @Test public void noParamMethod() throws Throwable {
   53.49 -        Method plus = methodClass.getMethod("fortyTwo");
   53.50 -        try {
   53.51 -            final Object val = plus.invoke(null);
   53.52 -            assertTrue(val instanceof Number, "A number returned " + val);
   53.53 -            assertEquals(((Number)val).intValue(), 42);
   53.54 -        } catch (InvocationTargetException ex) {
   53.55 -            throw ex.getTargetException();
   53.56 -        }
   53.57 -    }
   53.58 -    
   53.59 -    @Test public void testExecuteScript() throws Throwable {
   53.60 -        Method plus = methodClass.getMethod("plus", int.class, int.class);
   53.61 -        try {
   53.62 -            assertEquals(plus.invoke(null, 10, 20), 30);
   53.63 -        } catch (InvocationTargetException ex) {
   53.64 -            throw ex.getTargetException();
   53.65 -        }
   53.66 -    }
   53.67 -
   53.68 -    @Test public void overloadedMethod() throws Throwable {
   53.69 -        Method plus = methodClass.getMethod("plus", int.class);
   53.70 -        try {
   53.71 -            assertEquals(plus.invoke(null, 10), 10);
   53.72 -        } catch (InvocationTargetException ex) {
   53.73 -            throw ex.getTargetException();
   53.74 -        }
   53.75 -    }
   53.76 -    
   53.77 -    @Test public void instanceMethod() throws Throwable {
   53.78 -        Method plus = methodClass.getMethod("plusInst", int.class);
   53.79 -        Object inst = methodClass.newInstance();
   53.80 -        try {
   53.81 -            assertEquals(plus.invoke(inst, 10), 10);
   53.82 -        } catch (InvocationTargetException ex) {
   53.83 -            throw ex.getTargetException();
   53.84 -        }
   53.85 -    }
   53.86 -    
   53.87 -    @Test public void staticThis() throws Throwable {
   53.88 -        Method st = methodClass.getMethod("staticThis");
   53.89 -        try {
   53.90 -            assertNull(st.invoke(null));
   53.91 -        } catch (InvocationTargetException ex) {
   53.92 -            throw ex.getTargetException();
   53.93 -        }
   53.94 -    }
   53.95 -
   53.96 -    @Test public void getThis() throws Throwable {
   53.97 -        Object th = methodClass.newInstance();
   53.98 -        Method st = methodClass.getMethod("getThis");
   53.99 -        try {
  53.100 -            assertEquals(st.invoke(th), th);
  53.101 -        } catch (InvocationTargetException ex) {
  53.102 -            throw ex.getTargetException();
  53.103 -        }
  53.104 -    }
  53.105 -    
  53.106 -    @Test public void truth() throws Throwable {
  53.107 -        Method st = methodClass.getMethod("truth");
  53.108 -        assertTrue((st.getModifiers() & Modifier.STATIC) != 0, "Is static");
  53.109 -        assertEquals(st.invoke(null), Boolean.TRUE, "Can return boolean");
  53.110 -    }
  53.111 -    
  53.112 -    @Test public void callback() throws Throwable {
  53.113 -        class R implements Runnable {
  53.114 -            int cnt;
  53.115 -            
  53.116 -            @Override
  53.117 -            public void run() {
  53.118 -                cnt++;
  53.119 -            }
  53.120 -        }
  53.121 -        R r = new R();
  53.122 -        
  53.123 -        Method inc = methodClass.getMethod("callback", Runnable.class);
  53.124 -        inc.invoke(null, r);
  53.125 -        
  53.126 -        assertEquals(r.cnt, 1, "Callback happened");
  53.127 -    }
  53.128 -    
  53.129 -    @Test public void sumArray() throws Throwable {
  53.130 -        Method st = methodClass.getMethod("sumArr", int[].class);
  53.131 -        assertEquals(st.invoke(null, new int[] { 1, 2, 3 }), 6, "1+2+3 is six");
  53.132 -    }
  53.133 -    
  53.134 -    @Test public void javaScriptResource() throws Throwable {
  53.135 -        try {
  53.136 -            Method st = methodClass.getMethod("useExternalMul", int.class, int.class);
  53.137 -            assertEquals(st.invoke(null, 6, 7), 42, "Meaning of JavaScript?");
  53.138 -        } catch (InvocationTargetException ex) {
  53.139 -            throw ex.getTargetException();
  53.140 -        }
  53.141 -    }
  53.142 -    
  53.143 -    @Test public void callJavaScriptMethodOnOwnClass() throws Throwable {
  53.144 -        try {
  53.145 -            Object thiz = methodClass.newInstance();
  53.146 -            Method st = methodClass.getMethod("returnYourSelf", methodClass);
  53.147 -            assertEquals(st.invoke(null, thiz), thiz, "Returns this");
  53.148 -        } catch (InvocationTargetException ex) {
  53.149 -            throw ex.getTargetException();
  53.150 -        }
  53.151 -    }
  53.152 -    
  53.153 -    @Test public void callStaticJavaMethod() throws Throwable {
  53.154 -        Method st = methodClass.getMethod("staticCallback", int.class, int.class);
  53.155 -        assertEquals(st.invoke(null, 6, 7), 42, "Meaning of JavaScript?");
  53.156 -    }
  53.157 -
  53.158 -    @Test public void callStaticStringParamMethod() throws Throwable {
  53.159 -        Method st = methodClass.getMethod("parseInt", String.class);
  53.160 -        assertEquals(st.invoke(null, "42"), 42, "Meaning of JavaScript?");
  53.161 -    }
  53.162 -    
  53.163 -    @Test public void firstLong() throws Throwable {
  53.164 -        Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
  53.165 -        assertEquals(st.invoke(null, true, false, 10, 20), 10L, "Take first value");
  53.166 -    }
  53.167 -
  53.168 -    @Test public void secondLong() throws Throwable {
  53.169 -        Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
  53.170 -        assertEquals(st.invoke(null, false, true, 10, 20), 20L, "Take 2nd value");
  53.171 -    }
  53.172 -
  53.173 -    @Test public void bothLong() throws Throwable {
  53.174 -        Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
  53.175 -        assertEquals(st.invoke(null, true, true, 10, 20), 30L, "Take both values");
  53.176 -    }
  53.177 -    
  53.178 -    @Test public void recordError() throws Throwable {
  53.179 -        Method st = methodClass.getMethod("recordError", Object.class);
  53.180 -        assertEquals(st.invoke(methodClass.newInstance(), "Hello"), "Hello", "The same parameter returned");
  53.181 -    }
  53.182 -}
  53.183 \ No newline at end of file
    54.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JsClassLoaderTest.java	Mon Dec 16 17:16:02 2013 +0100
    54.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.3 @@ -1,133 +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.Closeable;
   54.27 -import java.io.Reader;
   54.28 -import org.apidesign.html.boot.spi.Fn;
   54.29 -import java.net.URL;
   54.30 -import java.net.URLClassLoader;
   54.31 -import java.util.ArrayList;
   54.32 -import java.util.Arrays;
   54.33 -import java.util.Enumeration;
   54.34 -import java.util.List;
   54.35 -import javax.script.Invocable;
   54.36 -import javax.script.ScriptEngine;
   54.37 -import javax.script.ScriptEngineManager;
   54.38 -import javax.script.ScriptException;
   54.39 -import org.testng.annotations.AfterClass;
   54.40 -import org.testng.annotations.BeforeClass;
   54.41 -import org.testng.annotations.BeforeMethod;
   54.42 -
   54.43 -/**
   54.44 - *
   54.45 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   54.46 - */
   54.47 -public class JsClassLoaderTest extends JsClassLoaderBase{
   54.48 -    private static Fn.Presenter loader;
   54.49 -
   54.50 -    @BeforeClass
   54.51 -    public static void setUpClass() throws Exception {
   54.52 -        ScriptEngineManager sem = new ScriptEngineManager();
   54.53 -        final ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
   54.54 -        
   54.55 -        final URL my = JsClassLoaderTest.class.getProtectionDomain().getCodeSource().getLocation();
   54.56 -        ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
   54.57 -        final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
   54.58 -        class MyCL extends JsClassLoader implements Fn.Presenter {
   54.59 -
   54.60 -            public MyCL(ClassLoader parent) {
   54.61 -                super(parent);
   54.62 -            }
   54.63 -            
   54.64 -            @Override
   54.65 -            protected URL findResource(String name) {
   54.66 -                return ul.getResource(name);
   54.67 -            }
   54.68 -            @Override
   54.69 -            public Fn defineFn(String code, String... names) {
   54.70 -                StringBuilder sb = new StringBuilder();
   54.71 -                sb.append("(function() {");
   54.72 -                sb.append("return function(");
   54.73 -                String sep = "";
   54.74 -                for (String n : names) {
   54.75 -                    sb.append(sep);
   54.76 -                    sb.append(n);
   54.77 -                    sep = ", ";
   54.78 -                }
   54.79 -                sb.append(") {");
   54.80 -                sb.append(code);
   54.81 -                sb.append("};");
   54.82 -                sb.append("})()");
   54.83 -                try {
   54.84 -                    final Object val = eng.eval(sb.toString());
   54.85 -                    return new Fn(this) {
   54.86 -                        @Override
   54.87 -                        public Object invoke(Object thiz, Object... args) throws Exception {
   54.88 -                            List<Object> all = new ArrayList<Object>(args.length + 1);
   54.89 -                            all.add(thiz == null ? val : thiz);
   54.90 -                            all.addAll(Arrays.asList(args));
   54.91 -                            Invocable inv = (Invocable)eng;
   54.92 -                            try {
   54.93 -                                Object ret = inv.invokeMethod(val, "call", all.toArray());
   54.94 -                                return val.equals(ret) ? null : ret;
   54.95 -                            } catch (Exception ex) {
   54.96 -                                throw ex;
   54.97 -                            }
   54.98 -                        }
   54.99 -                    };
  54.100 -                } catch (ScriptException ex) {
  54.101 -                    throw new LinkageError("Can't parse: " + sb, ex);
  54.102 -                }
  54.103 -            }
  54.104 -
  54.105 -            @Override
  54.106 -            protected Enumeration<URL> findResources(String name) {
  54.107 -                throw new UnsupportedOperationException();
  54.108 -            }
  54.109 -
  54.110 -            @Override
  54.111 -            public void loadScript(Reader code) throws ScriptException {
  54.112 -                eng.eval(code);
  54.113 -            }
  54.114 -
  54.115 -            @Override
  54.116 -            public void displayPage(URL page, Runnable onPageLoad) {
  54.117 -                throw new UnsupportedOperationException();
  54.118 -            }
  54.119 -        };
  54.120 -        
  54.121 -        MyCL l = new MyCL(parent);
  54.122 -        Closeable close = FnContext.activate(l);
  54.123 -        methodClass = l.loadClass(JsMethods.class.getName());
  54.124 -        close.close();
  54.125 -        loader = l;
  54.126 -    }
  54.127 -    
  54.128 -    @BeforeMethod public void initPresenter() {
  54.129 -        FnContext.currentPresenter(loader);
  54.130 -    }
  54.131 -
  54.132 -    @AfterClass
  54.133 -    public static void cleanUp() {
  54.134 -        methodClass = null;
  54.135 -    }
  54.136 -}
  54.137 \ No newline at end of file
    55.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JsMethods.java	Mon Dec 16 17:16:02 2013 +0100
    55.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.3 @@ -1,107 +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 net.java.html.js.JavaScriptBody;
   55.27 -import net.java.html.js.JavaScriptResource;
   55.28 -
   55.29 -
   55.30 -/**
   55.31 - *
   55.32 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   55.33 - */
   55.34 -@JavaScriptResource("jsmethods.js")
   55.35 -public class JsMethods {
   55.36 -    private Object value;
   55.37 -    
   55.38 -    @JavaScriptBody(args = {}, body = "return 42;")
   55.39 -    public static Object fortyTwo() {
   55.40 -        return -42;
   55.41 -    }
   55.42 -    
   55.43 -    @JavaScriptBody(args = {"x", "y" }, body = "return x + y;")
   55.44 -    public static native int plus(int x, int y);
   55.45 -    
   55.46 -    @JavaScriptBody(args = {"x"}, body = "return x;")
   55.47 -    public static native int plus(int x);
   55.48 -    
   55.49 -    @JavaScriptBody(args = {}, body = "return this;")
   55.50 -    public static native Object staticThis();
   55.51 -    
   55.52 -    @JavaScriptBody(args = {}, body = "return this;")
   55.53 -    public native Object getThis();
   55.54 -    @JavaScriptBody(args = {"x"}, body = "return x;")
   55.55 -    public native int plusInst(int x);
   55.56 -    
   55.57 -    @JavaScriptBody(args = {}, body = "return true;")
   55.58 -    public static boolean truth() {
   55.59 -        return false;
   55.60 -    }
   55.61 -    
   55.62 -    @JavaScriptBody(args = { "r" }, javacall=true, body = "r.@java.lang.Runnable::run()();")
   55.63 -    public static native void callback(Runnable r);
   55.64 -    
   55.65 -    @JavaScriptBody(args = { "at", "arr" }, javacall = true, body =
   55.66 -          "var a = 0;\n"
   55.67 -        + "for (var i = 0; i < arr.length; i++) {\n"
   55.68 -        + "  a = at.@org.apidesign.html.boot.impl.Arithm::sumTwo(II)(a, arr[i]);\n"
   55.69 -        + "}\n"
   55.70 -        + "return a;"
   55.71 -    )
   55.72 -    private static native int sumArr(Arithm at, int... arr);
   55.73 -    
   55.74 -    public static int sumArr(int... arr) {
   55.75 -        return sumArr(new Arithm(), arr);
   55.76 -    }
   55.77 -    
   55.78 -    @JavaScriptBody(args = { "x", "y" }, body = "return mul(x, y);")
   55.79 -    public static native int useExternalMul(int x, int y);
   55.80 -    
   55.81 -    @JavaScriptBody(args = { "m" }, javacall = true, body = "return m.@org.apidesign.html.boot.impl.JsMethods::getThis()();")
   55.82 -    public static native JsMethods returnYourSelf(JsMethods m);
   55.83 -    
   55.84 -    @JavaScriptBody(args = { "x", "y" }, javacall = true, body = "return @org.apidesign.html.boot.impl.JsMethods::useExternalMul(II)(x, y);")
   55.85 -    public static native int staticCallback(int x, int y);
   55.86 -
   55.87 -    @JavaScriptBody(args = { "v" }, javacall = true, body = "return @java.lang.Integer::parseInt(Ljava/lang/String;)(v);")
   55.88 -    public static native int parseInt(String v);
   55.89 -    
   55.90 -    @JavaScriptBody(args = { "useA", "useB", "a", "b" }, body = "var l = 0;"
   55.91 -        + "if (useA) l += a;\n"
   55.92 -        + "if (useB) l += b;\n"
   55.93 -        + "return l;\n"
   55.94 -    )
   55.95 -    public static native long chooseLong(boolean useA, boolean useB, long a, long b);
   55.96 -    
   55.97 -    protected void onError(Object o) throws Exception {
   55.98 -        value = o;
   55.99 -    }
  55.100 -    
  55.101 -    Object getError() {
  55.102 -        return value;
  55.103 -    }
  55.104 -    
  55.105 -    @JavaScriptBody(args = { "err" }, javacall = true, body = 
  55.106 -        "this.@org.apidesign.html.boot.impl.JsMethods::onError(Ljava/lang/Object;)(err);"
  55.107 -      + "return this.@org.apidesign.html.boot.impl.JsMethods::getError()();"
  55.108 -    )
  55.109 -    public native Object recordError(Object err);
  55.110 -}
    56.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/Arithm.java	Mon Dec 16 17:16:40 2013 +0100
    56.3 @@ -0,0 +1,53 @@
    56.4 +/**
    56.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    56.6 + *
    56.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    56.8 + *
    56.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   56.10 + * Other names may be trademarks of their respective owners.
   56.11 + *
   56.12 + * The contents of this file are subject to the terms of either the GNU
   56.13 + * General Public License Version 2 only ("GPL") or the Common
   56.14 + * Development and Distribution License("CDDL") (collectively, the
   56.15 + * "License"). You may not use this file except in compliance with the
   56.16 + * License. You can obtain a copy of the License at
   56.17 + * http://www.netbeans.org/cddl-gplv2.html
   56.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   56.19 + * specific language governing permissions and limitations under the
   56.20 + * License.  When distributing the software, include this License Header
   56.21 + * Notice in each file and include the License file at
   56.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   56.23 + * particular file as subject to the "Classpath" exception as provided
   56.24 + * by Oracle in the GPL Version 2 section of the License file that
   56.25 + * accompanied this code. If applicable, add the following below the
   56.26 + * License Header, with the fields enclosed by brackets [] replaced by
   56.27 + * your own identifying information:
   56.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   56.29 + *
   56.30 + * Contributor(s):
   56.31 + *
   56.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   56.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   56.34 + *
   56.35 + * If you wish your version of this file to be governed by only the CDDL
   56.36 + * or only the GPL Version 2, indicate your decision by adding
   56.37 + * "[Contributor] elects to include this software in this distribution
   56.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   56.39 + * single choice of license, a recipient has the option to distribute
   56.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   56.41 + * to extend the choice of license to its licensees as provided above.
   56.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   56.43 + * Version 2 license, then the option applies only if the new code is
   56.44 + * made subject to such option by the copyright holder.
   56.45 + */
   56.46 +package org.netbeans.html.boot.impl;
   56.47 +
   56.48 +/**
   56.49 + *
   56.50 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   56.51 + */
   56.52 +public class Arithm {
   56.53 +    public int sumTwo(int a, int b) {
   56.54 +        return a + b;
   56.55 +    }
   56.56 +}
    57.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/Compile.java	Mon Dec 16 17:16:40 2013 +0100
    57.3 @@ -0,0 +1,291 @@
    57.4 +/**
    57.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    57.6 + *
    57.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    57.8 + *
    57.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   57.10 + * Other names may be trademarks of their respective owners.
   57.11 + *
   57.12 + * The contents of this file are subject to the terms of either the GNU
   57.13 + * General Public License Version 2 only ("GPL") or the Common
   57.14 + * Development and Distribution License("CDDL") (collectively, the
   57.15 + * "License"). You may not use this file except in compliance with the
   57.16 + * License. You can obtain a copy of the License at
   57.17 + * http://www.netbeans.org/cddl-gplv2.html
   57.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   57.19 + * specific language governing permissions and limitations under the
   57.20 + * License.  When distributing the software, include this License Header
   57.21 + * Notice in each file and include the License file at
   57.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   57.23 + * particular file as subject to the "Classpath" exception as provided
   57.24 + * by Oracle in the GPL Version 2 section of the License file that
   57.25 + * accompanied this code. If applicable, add the following below the
   57.26 + * License Header, with the fields enclosed by brackets [] replaced by
   57.27 + * your own identifying information:
   57.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   57.29 + *
   57.30 + * Contributor(s):
   57.31 + *
   57.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   57.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   57.34 + *
   57.35 + * If you wish your version of this file to be governed by only the CDDL
   57.36 + * or only the GPL Version 2, indicate your decision by adding
   57.37 + * "[Contributor] elects to include this software in this distribution
   57.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   57.39 + * single choice of license, a recipient has the option to distribute
   57.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   57.41 + * to extend the choice of license to its licensees as provided above.
   57.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   57.43 + * Version 2 license, then the option applies only if the new code is
   57.44 + * made subject to such option by the copyright holder.
   57.45 + */
   57.46 +package org.netbeans.html.boot.impl;
   57.47 +
   57.48 +import java.io.ByteArrayInputStream;
   57.49 +import java.io.ByteArrayOutputStream;
   57.50 +import java.io.IOException;
   57.51 +import java.io.InputStream;
   57.52 +import java.io.OutputStream;
   57.53 +import java.net.URI;
   57.54 +import java.net.URISyntaxException;
   57.55 +import java.util.ArrayList;
   57.56 +import java.util.Arrays;
   57.57 +import java.util.HashMap;
   57.58 +import java.util.List;
   57.59 +import java.util.Locale;
   57.60 +import java.util.Map;
   57.61 +import java.util.regex.Matcher;
   57.62 +import java.util.regex.Pattern;
   57.63 +import javax.tools.Diagnostic;
   57.64 +import javax.tools.DiagnosticListener;
   57.65 +import javax.tools.FileObject;
   57.66 +import javax.tools.ForwardingJavaFileManager;
   57.67 +import javax.tools.JavaFileManager;
   57.68 +import javax.tools.JavaFileObject;
   57.69 +import javax.tools.JavaFileObject.Kind;
   57.70 +import javax.tools.SimpleJavaFileObject;
   57.71 +import javax.tools.StandardJavaFileManager;
   57.72 +import javax.tools.StandardLocation;
   57.73 +import javax.tools.ToolProvider;
   57.74 +import static org.testng.Assert.assertTrue;
   57.75 +import static org.testng.Assert.assertFalse;
   57.76 +import static org.testng.Assert.fail;
   57.77 +
   57.78 +/**
   57.79 + *
   57.80 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   57.81 + */
   57.82 +final class Compile implements DiagnosticListener<JavaFileObject> {
   57.83 +    private final List<Diagnostic<? extends JavaFileObject>> errors = 
   57.84 +            new ArrayList<Diagnostic<? extends JavaFileObject>>();
   57.85 +    private final Map<String, byte[]> classes;
   57.86 +    private final String pkg;
   57.87 +    private final String cls;
   57.88 +    private final String html;
   57.89 +    private final String sourceLevel;
   57.90 +
   57.91 +    private Compile(String html, String code, String sl) throws IOException {
   57.92 +        this.pkg = findPkg(code);
   57.93 +        this.cls = findCls(code);
   57.94 +        this.html = html;
   57.95 +        this.sourceLevel = sl;
   57.96 +        classes = compile(html, code);
   57.97 +    }
   57.98 +
   57.99 +    /** Performs compilation of given HTML page and associated Java code
  57.100 +     */
  57.101 +    public static Compile create(String html, String code) throws IOException {
  57.102 +        return create(html, code, "1.7");
  57.103 +    }
  57.104 +    static Compile create(String html, String code, String sourceLevel) throws IOException {
  57.105 +        return new Compile(html, code, sourceLevel);
  57.106 +    }
  57.107 +    
  57.108 +    /** Checks for given class among compiled resources */
  57.109 +    public byte[] get(String res) {
  57.110 +        return classes.get(res);
  57.111 +    }
  57.112 +    
  57.113 +    /** Obtains errors created during compilation.
  57.114 +     */
  57.115 +    public List<Diagnostic<? extends JavaFileObject>> getErrors() {
  57.116 +        List<Diagnostic<? extends JavaFileObject>> err;
  57.117 +        err = new ArrayList<Diagnostic<? extends JavaFileObject>>();
  57.118 +        for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
  57.119 +            if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
  57.120 +                err.add(diagnostic);
  57.121 +            }
  57.122 +        }
  57.123 +        return err;
  57.124 +    }
  57.125 +    
  57.126 +    private Map<String, byte[]> compile(final String html, final String code) throws IOException {
  57.127 +        StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
  57.128 +
  57.129 +        final Map<String, ByteArrayOutputStream> class2BAOS;
  57.130 +        class2BAOS = new HashMap<String, ByteArrayOutputStream>();
  57.131 +
  57.132 +        JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
  57.133 +            @Override
  57.134 +            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  57.135 +                return code;
  57.136 +            }
  57.137 +        };
  57.138 +        final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
  57.139 +            @Override
  57.140 +            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  57.141 +                return html;
  57.142 +            }
  57.143 +
  57.144 +            @Override
  57.145 +            public InputStream openInputStream() throws IOException {
  57.146 +                return new ByteArrayInputStream(html.getBytes());
  57.147 +            }
  57.148 +        };
  57.149 +        
  57.150 +        final URI scratch;
  57.151 +        try {
  57.152 +            scratch = new URI("mem://mem3");
  57.153 +        } catch (URISyntaxException ex) {
  57.154 +            throw new IOException(ex);
  57.155 +        }
  57.156 +        
  57.157 +        JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
  57.158 +            @Override
  57.159 +            public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
  57.160 +                if (kind  == Kind.CLASS) {
  57.161 +                    final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
  57.162 +
  57.163 +                    class2BAOS.put(className.replace('.', '/') + ".class", buffer);
  57.164 +                    return new SimpleJavaFileObject(sibling.toUri(), kind) {
  57.165 +                        @Override
  57.166 +                        public OutputStream openOutputStream() throws IOException {
  57.167 +                            return buffer;
  57.168 +                        }
  57.169 +                    };
  57.170 +                }
  57.171 +                
  57.172 +                if (kind == Kind.SOURCE) {
  57.173 +                    final String n = className.replace('.', '/') + ".java";
  57.174 +                    final URI un;
  57.175 +                    try {
  57.176 +                        un = new URI("mem://" + n);
  57.177 +                    } catch (URISyntaxException ex) {
  57.178 +                        throw new IOException(ex);
  57.179 +                    }
  57.180 +                    return new VirtFO(un/*sibling.toUri()*/, kind, n);
  57.181 +                }
  57.182 +                
  57.183 +                throw new IllegalStateException();
  57.184 +            }
  57.185 +
  57.186 +            @Override
  57.187 +            public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
  57.188 +                if (location == StandardLocation.SOURCE_PATH) {
  57.189 +                    if (packageName.equals(pkg)) {
  57.190 +                        return htmlFile;
  57.191 +                    }
  57.192 +                }
  57.193 +                
  57.194 +                return null;
  57.195 +            }
  57.196 +
  57.197 +            @Override
  57.198 +            public boolean isSameFile(FileObject a, FileObject b) {
  57.199 +                if (a instanceof VirtFO && b instanceof VirtFO) {
  57.200 +                    return ((VirtFO)a).getName().equals(((VirtFO)b).getName());
  57.201 +                }
  57.202 +                
  57.203 +                return super.isSameFile(a, b);
  57.204 +            }
  57.205 +
  57.206 +            class VirtFO extends SimpleJavaFileObject {
  57.207 +
  57.208 +                private final String n;
  57.209 +
  57.210 +                public VirtFO(URI uri, Kind kind, String n) {
  57.211 +                    super(uri, kind);
  57.212 +                    this.n = n;
  57.213 +                }
  57.214 +                private final ByteArrayOutputStream data = new ByteArrayOutputStream();
  57.215 +
  57.216 +                @Override
  57.217 +                public OutputStream openOutputStream() throws IOException {
  57.218 +                    return data;
  57.219 +                }
  57.220 +
  57.221 +                @Override
  57.222 +                public String getName() {
  57.223 +                    return n;
  57.224 +                }
  57.225 +
  57.226 +                @Override
  57.227 +                public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  57.228 +                    data.close();
  57.229 +                    return new String(data.toByteArray());
  57.230 +                }
  57.231 +            }
  57.232 +        };
  57.233 +
  57.234 +        ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", sourceLevel, "-target", "1.7"), null, Arrays.asList(file)).call();
  57.235 +
  57.236 +        Map<String, byte[]> result = new HashMap<String, byte[]>();
  57.237 +
  57.238 +        for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
  57.239 +            result.put(e.getKey(), e.getValue().toByteArray());
  57.240 +        }
  57.241 +
  57.242 +        return result;
  57.243 +    }
  57.244 +
  57.245 +
  57.246 +    @Override
  57.247 +    public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
  57.248 +        errors.add(diagnostic);
  57.249 +    }
  57.250 +    private static String findPkg(String java) throws IOException {
  57.251 +        Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
  57.252 +        Matcher m = p.matcher(java);
  57.253 +        if (!m.find()) {
  57.254 +            throw new IOException("Can't find package declaration in the java file");
  57.255 +        }
  57.256 +        String pkg = m.group(1);
  57.257 +        return pkg;
  57.258 +    }
  57.259 +    private static String findCls(String java) throws IOException {
  57.260 +        Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
  57.261 +        Matcher m = p.matcher(java);
  57.262 +        if (!m.find()) {
  57.263 +            throw new IOException("Can't find package declaration in the java file");
  57.264 +        }
  57.265 +        String cls = m.group(1);
  57.266 +        return cls;
  57.267 +    }
  57.268 +
  57.269 +    String getHtml() {
  57.270 +        String fqn = "'" + pkg + '.' + cls + "'";
  57.271 +        return html.replace("'${fqn}'", fqn);
  57.272 +    }
  57.273 +    void assertErrors() {
  57.274 +        assertFalse(getErrors().isEmpty(), "There are supposed to be some errors");
  57.275 +    }
  57.276 +
  57.277 +    void assertError(String expMsg) {
  57.278 +        StringBuilder sb = new StringBuilder();
  57.279 +        sb.append("Can't find ").append(expMsg).append(" among:");
  57.280 +        for (Diagnostic<? extends JavaFileObject> e : errors) {
  57.281 +            String msg = e.getMessage(Locale.US);
  57.282 +            if (msg.contains(expMsg)) {
  57.283 +                return;
  57.284 +            }
  57.285 +            sb.append("\n");
  57.286 +            sb.append(msg);
  57.287 +        }
  57.288 +        fail(sb.toString());
  57.289 +    }
  57.290 +
  57.291 +    void assertNoErrors() {
  57.292 +        assertTrue(getErrors().isEmpty(), "No errors expected: " + getErrors());
  57.293 +    }
  57.294 +}
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/FnTest.java	Mon Dec 16 17:16:40 2013 +0100
    58.3 @@ -0,0 +1,148 @@
    58.4 +/**
    58.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    58.6 + *
    58.7 + * Copyright 1997-2010 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 +import java.io.Closeable;
   58.49 +import java.io.Reader;
   58.50 +import java.net.URL;
   58.51 +import java.net.URLClassLoader;
   58.52 +import java.util.ArrayList;
   58.53 +import java.util.Arrays;
   58.54 +import java.util.Collection;
   58.55 +import java.util.List;
   58.56 +import javax.script.Invocable;
   58.57 +import javax.script.ScriptEngine;
   58.58 +import javax.script.ScriptEngineManager;
   58.59 +import javax.script.ScriptException;
   58.60 +import org.apidesign.html.boot.spi.Fn;
   58.61 +import org.testng.annotations.BeforeClass;
   58.62 +import org.testng.annotations.BeforeMethod;
   58.63 +
   58.64 +/**
   58.65 + *
   58.66 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   58.67 + */
   58.68 +public class FnTest extends JsClassLoaderBase {
   58.69 +    private static Fn.Presenter presenter;
   58.70 +    
   58.71 +    public FnTest() {
   58.72 +    }
   58.73 +
   58.74 +    @BeforeClass
   58.75 +    public static void createClassLoader() throws Exception {
   58.76 +        ScriptEngineManager sem = new ScriptEngineManager();
   58.77 +        final ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
   58.78 +        
   58.79 +        final URL my = FnTest.class.getProtectionDomain().getCodeSource().getLocation();
   58.80 +        ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
   58.81 +        final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
   58.82 +        
   58.83 +        class Impl implements FindResources, Fn.Presenter {
   58.84 +            @Override
   58.85 +            public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough) {
   58.86 +                URL u = ul.findResource(path);
   58.87 +                if (u != null) {
   58.88 +                    results.add(u);
   58.89 +                }
   58.90 +            }
   58.91 +
   58.92 +            @Override
   58.93 +            public Fn defineFn(String code, String... names) {
   58.94 +                StringBuilder sb = new StringBuilder();
   58.95 +                sb.append("(function() {");
   58.96 +                sb.append("return function(");
   58.97 +                String sep = "";
   58.98 +                for (String n : names) {
   58.99 +                    sb.append(sep);
  58.100 +                    sb.append(n);
  58.101 +                    sep = ", ";
  58.102 +                }
  58.103 +                sb.append(") {");
  58.104 +                sb.append(code);
  58.105 +                sb.append("};");
  58.106 +                sb.append("})()");
  58.107 +                try {
  58.108 +                    final Object val = eng.eval(sb.toString());
  58.109 +                    return new Fn(this) {
  58.110 +                        @Override
  58.111 +                        public Object invoke(Object thiz, Object... args) throws Exception {
  58.112 +                            List<Object> all = new ArrayList<Object>(args.length + 1);
  58.113 +                            all.add(thiz == null ? val : thiz);
  58.114 +                            all.addAll(Arrays.asList(args));
  58.115 +                            Invocable inv = (Invocable)eng;
  58.116 +                            try {
  58.117 +                                Object ret = inv.invokeMethod(val, "call", all.toArray());
  58.118 +                                return val.equals(ret) ? null : ret;
  58.119 +                            } catch (ScriptException ex) {
  58.120 +                                throw ex;
  58.121 +                            }
  58.122 +                        }
  58.123 +                    };
  58.124 +                } catch (ScriptException ex) {
  58.125 +                    throw new LinkageError("Can't parse: " + sb, ex);
  58.126 +                }
  58.127 +            }
  58.128 +
  58.129 +            @Override
  58.130 +            public void displayPage(URL resource, Runnable r) {
  58.131 +                throw new UnsupportedOperationException();
  58.132 +            }
  58.133 +
  58.134 +            @Override
  58.135 +            public void loadScript(Reader code) throws Exception {
  58.136 +                eng.eval(code);
  58.137 +            }
  58.138 +        }
  58.139 +        Impl impl = new Impl();
  58.140 +        ClassLoader loader = FnUtils.newLoader(impl, impl, parent);
  58.141 +        presenter = impl;
  58.142 +        
  58.143 +        Closeable close = FnContext.activate(impl);
  58.144 +        methodClass = loader.loadClass(JsMethods.class.getName());
  58.145 +        close.close();
  58.146 +    }
  58.147 +
  58.148 +    @BeforeMethod public void initPresenter() {
  58.149 +        FnContext.currentPresenter(presenter);
  58.150 +    }
  58.151 +}
    59.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/JavaScriptProcesorTest.java	Mon Dec 16 17:16:40 2013 +0100
    59.3 @@ -0,0 +1,129 @@
    59.4 +/**
    59.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    59.6 + *
    59.7 + * Copyright 1997-2010 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.IOException;
   59.49 +import java.lang.reflect.Field;
   59.50 +import java.lang.reflect.Method;
   59.51 +import static org.testng.Assert.assertEquals;
   59.52 +import static org.testng.Assert.assertTrue;
   59.53 +import org.testng.annotations.Test;
   59.54 +
   59.55 +/**
   59.56 + *
   59.57 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   59.58 + */
   59.59 +public class JavaScriptProcesorTest {
   59.60 +    
   59.61 +    @Test public void detectCallbackToNonExistingClass() throws IOException {
   59.62 +        String code = "package x.y.z;\n"
   59.63 +            + "import net.java.html.js.JavaScriptBody;\n"
   59.64 +            + "class X {\n"
   59.65 +            + "  @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
   59.66 +            + "    \"r.@java.lang.Runable::run()();\"\n" // typo
   59.67 +            + "  )\n"
   59.68 +            + "  private static native void callback(Runnable r);\n"
   59.69 +            + "}\n";
   59.70 +        
   59.71 +        Compile c = Compile.create("", code);
   59.72 +        c.assertErrors();
   59.73 +        c.assertError("java.lang.Runable"); // typo
   59.74 +    }
   59.75 +
   59.76 +    @Test public void detectCallbackToNonExistingMethod() throws IOException {
   59.77 +        String code = "package x.y.z;\n"
   59.78 +            + "import net.java.html.js.JavaScriptBody;\n"
   59.79 +            + "class X {\n"
   59.80 +            + "  @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
   59.81 +            + "    \"r.@java.lang.Runnable::cancel()();\"\n"
   59.82 +            + "  )\n"
   59.83 +            + "  private static native void callback(Runnable r);\n"
   59.84 +            + "}\n";
   59.85 +        
   59.86 +        Compile c = Compile.create("", code);
   59.87 +        c.assertErrors();
   59.88 +        c.assertError("method cancel");
   59.89 +    }
   59.90 +
   59.91 +    @Test public void detectCallbackToNonExistingParams() throws IOException {
   59.92 +        String code = "package x.y.z;\n"
   59.93 +            + "import net.java.html.js.JavaScriptBody;\n"
   59.94 +            + "class X {\n"
   59.95 +            + "  @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
   59.96 +            + "    \"r.@java.lang.Runnable::run(I)(10);\"\n"
   59.97 +            + "  )\n"
   59.98 +            + "  private static native void callback(Runnable r);\n"
   59.99 +            + "}\n";
  59.100 +        
  59.101 +        Compile c = Compile.create("", code);
  59.102 +        c.assertErrors();
  59.103 +        c.assertError("wrong parameters: (I)");
  59.104 +    }
  59.105 +
  59.106 +    @Test public void objectTypeParamsAreOK() throws IOException {
  59.107 +        String code = "package x.y.z;\n"
  59.108 +            + "import net.java.html.js.JavaScriptBody;\n"
  59.109 +            + "class X {\n"
  59.110 +            + "  @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
  59.111 +            + "    \"r.@java.lang.Object::equals(Ljava/lang/Object;)(null);\"\n"
  59.112 +            + "  )\n"
  59.113 +            + "  private static native void testEqual(Object r);\n"
  59.114 +            + "}\n";
  59.115 +        
  59.116 +        Compile c = Compile.create("", code);
  59.117 +        c.assertNoErrors();
  59.118 +    }
  59.119 +    
  59.120 +    @Test public void generatesCallbacksThatReturnObject() throws Exception {
  59.121 +        Class<?> callbacksForTestPkg = Class.forName("org.netbeans.html.boot.impl.$JsCallbacks$");
  59.122 +        Method m = callbacksForTestPkg.getDeclaredMethod("java_lang_Runnable$run$", Runnable.class);
  59.123 +        assertEquals(m.getReturnType(), Object.class, "All methods always return object");
  59.124 +    }
  59.125 +    
  59.126 +    @Test public void hasInstanceField() throws Exception {
  59.127 +        Class<?> callbacksForTestPkg = Class.forName("org.netbeans.html.boot.impl.$JsCallbacks$");
  59.128 +        Field f = callbacksForTestPkg.getDeclaredField("VM");
  59.129 +        f.setAccessible(true);
  59.130 +        assertTrue(callbacksForTestPkg.isInstance(f.get(null)), "Singleton field VM");
  59.131 +    }
  59.132 +}
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/JsClassLoaderBase.java	Mon Dec 16 17:16:40 2013 +0100
    60.3 @@ -0,0 +1,201 @@
    60.4 +/**
    60.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    60.6 + *
    60.7 + * Copyright 1997-2010 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.lang.reflect.InvocationTargetException;
   60.49 +import java.lang.reflect.Method;
   60.50 +import java.lang.reflect.Modifier;
   60.51 +import static org.testng.Assert.*;
   60.52 +import org.testng.annotations.BeforeMethod;
   60.53 +import org.testng.annotations.Test;
   60.54 +
   60.55 +/**
   60.56 + *
   60.57 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   60.58 + */
   60.59 +public class JsClassLoaderBase {
   60.60 +    protected static Class<?> methodClass;
   60.61 +    
   60.62 +    public JsClassLoaderBase() {
   60.63 +    }
   60.64 +    
   60.65 +    @BeforeMethod
   60.66 +    public void assertClassDefined() {
   60.67 +        assertNotNull(methodClass, "BeforeClass set up code should provide methodClass");
   60.68 +    }
   60.69 +
   60.70 +    @Test public void noParamMethod() throws Throwable {
   60.71 +        Method plus = methodClass.getMethod("fortyTwo");
   60.72 +        try {
   60.73 +            final Object val = plus.invoke(null);
   60.74 +            assertTrue(val instanceof Number, "A number returned " + val);
   60.75 +            assertEquals(((Number)val).intValue(), 42);
   60.76 +        } catch (InvocationTargetException ex) {
   60.77 +            throw ex.getTargetException();
   60.78 +        }
   60.79 +    }
   60.80 +    
   60.81 +    @Test public void testExecuteScript() throws Throwable {
   60.82 +        Method plus = methodClass.getMethod("plus", int.class, int.class);
   60.83 +        try {
   60.84 +            assertEquals(plus.invoke(null, 10, 20), 30);
   60.85 +        } catch (InvocationTargetException ex) {
   60.86 +            throw ex.getTargetException();
   60.87 +        }
   60.88 +    }
   60.89 +
   60.90 +    @Test public void overloadedMethod() throws Throwable {
   60.91 +        Method plus = methodClass.getMethod("plus", int.class);
   60.92 +        try {
   60.93 +            assertEquals(plus.invoke(null, 10), 10);
   60.94 +        } catch (InvocationTargetException ex) {
   60.95 +            throw ex.getTargetException();
   60.96 +        }
   60.97 +    }
   60.98 +    
   60.99 +    @Test public void instanceMethod() throws Throwable {
  60.100 +        Method plus = methodClass.getMethod("plusInst", int.class);
  60.101 +        Object inst = methodClass.newInstance();
  60.102 +        try {
  60.103 +            assertEquals(plus.invoke(inst, 10), 10);
  60.104 +        } catch (InvocationTargetException ex) {
  60.105 +            throw ex.getTargetException();
  60.106 +        }
  60.107 +    }
  60.108 +    
  60.109 +    @Test public void staticThis() throws Throwable {
  60.110 +        Method st = methodClass.getMethod("staticThis");
  60.111 +        try {
  60.112 +            assertNull(st.invoke(null));
  60.113 +        } catch (InvocationTargetException ex) {
  60.114 +            throw ex.getTargetException();
  60.115 +        }
  60.116 +    }
  60.117 +
  60.118 +    @Test public void getThis() throws Throwable {
  60.119 +        Object th = methodClass.newInstance();
  60.120 +        Method st = methodClass.getMethod("getThis");
  60.121 +        try {
  60.122 +            assertEquals(st.invoke(th), th);
  60.123 +        } catch (InvocationTargetException ex) {
  60.124 +            throw ex.getTargetException();
  60.125 +        }
  60.126 +    }
  60.127 +    
  60.128 +    @Test public void truth() throws Throwable {
  60.129 +        Method st = methodClass.getMethod("truth");
  60.130 +        assertTrue((st.getModifiers() & Modifier.STATIC) != 0, "Is static");
  60.131 +        assertEquals(st.invoke(null), Boolean.TRUE, "Can return boolean");
  60.132 +    }
  60.133 +    
  60.134 +    @Test public void callback() throws Throwable {
  60.135 +        class R implements Runnable {
  60.136 +            int cnt;
  60.137 +            
  60.138 +            @Override
  60.139 +            public void run() {
  60.140 +                cnt++;
  60.141 +            }
  60.142 +        }
  60.143 +        R r = new R();
  60.144 +        
  60.145 +        Method inc = methodClass.getMethod("callback", Runnable.class);
  60.146 +        inc.invoke(null, r);
  60.147 +        
  60.148 +        assertEquals(r.cnt, 1, "Callback happened");
  60.149 +    }
  60.150 +    
  60.151 +    @Test public void sumArray() throws Throwable {
  60.152 +        Method st = methodClass.getMethod("sumArr", int[].class);
  60.153 +        assertEquals(st.invoke(null, new int[] { 1, 2, 3 }), 6, "1+2+3 is six");
  60.154 +    }
  60.155 +    
  60.156 +    @Test public void javaScriptResource() throws Throwable {
  60.157 +        try {
  60.158 +            Method st = methodClass.getMethod("useExternalMul", int.class, int.class);
  60.159 +            assertEquals(st.invoke(null, 6, 7), 42, "Meaning of JavaScript?");
  60.160 +        } catch (InvocationTargetException ex) {
  60.161 +            throw ex.getTargetException();
  60.162 +        }
  60.163 +    }
  60.164 +    
  60.165 +    @Test public void callJavaScriptMethodOnOwnClass() throws Throwable {
  60.166 +        try {
  60.167 +            Object thiz = methodClass.newInstance();
  60.168 +            Method st = methodClass.getMethod("returnYourSelf", methodClass);
  60.169 +            assertEquals(st.invoke(null, thiz), thiz, "Returns this");
  60.170 +        } catch (InvocationTargetException ex) {
  60.171 +            throw ex.getTargetException();
  60.172 +        }
  60.173 +    }
  60.174 +    
  60.175 +    @Test public void callStaticJavaMethod() throws Throwable {
  60.176 +        Method st = methodClass.getMethod("staticCallback", int.class, int.class);
  60.177 +        assertEquals(st.invoke(null, 6, 7), 42, "Meaning of JavaScript?");
  60.178 +    }
  60.179 +
  60.180 +    @Test public void callStaticStringParamMethod() throws Throwable {
  60.181 +        Method st = methodClass.getMethod("parseInt", String.class);
  60.182 +        assertEquals(st.invoke(null, "42"), 42, "Meaning of JavaScript?");
  60.183 +    }
  60.184 +    
  60.185 +    @Test public void firstLong() throws Throwable {
  60.186 +        Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
  60.187 +        assertEquals(st.invoke(null, true, false, 10, 20), 10L, "Take first value");
  60.188 +    }
  60.189 +
  60.190 +    @Test public void secondLong() throws Throwable {
  60.191 +        Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
  60.192 +        assertEquals(st.invoke(null, false, true, 10, 20), 20L, "Take 2nd value");
  60.193 +    }
  60.194 +
  60.195 +    @Test public void bothLong() throws Throwable {
  60.196 +        Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
  60.197 +        assertEquals(st.invoke(null, true, true, 10, 20), 30L, "Take both values");
  60.198 +    }
  60.199 +    
  60.200 +    @Test public void recordError() throws Throwable {
  60.201 +        Method st = methodClass.getMethod("recordError", Object.class);
  60.202 +        assertEquals(st.invoke(methodClass.newInstance(), "Hello"), "Hello", "The same parameter returned");
  60.203 +    }
  60.204 +}
  60.205 \ No newline at end of file
    61.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/JsClassLoaderTest.java	Mon Dec 16 17:16:40 2013 +0100
    61.3 @@ -0,0 +1,155 @@
    61.4 +/**
    61.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    61.6 + *
    61.7 + * Copyright 1997-2010 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.Closeable;
   61.49 +import java.io.Reader;
   61.50 +import org.apidesign.html.boot.spi.Fn;
   61.51 +import java.net.URL;
   61.52 +import java.net.URLClassLoader;
   61.53 +import java.util.ArrayList;
   61.54 +import java.util.Arrays;
   61.55 +import java.util.Enumeration;
   61.56 +import java.util.List;
   61.57 +import javax.script.Invocable;
   61.58 +import javax.script.ScriptEngine;
   61.59 +import javax.script.ScriptEngineManager;
   61.60 +import javax.script.ScriptException;
   61.61 +import org.testng.annotations.AfterClass;
   61.62 +import org.testng.annotations.BeforeClass;
   61.63 +import org.testng.annotations.BeforeMethod;
   61.64 +
   61.65 +/**
   61.66 + *
   61.67 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   61.68 + */
   61.69 +public class JsClassLoaderTest extends JsClassLoaderBase{
   61.70 +    private static Fn.Presenter loader;
   61.71 +
   61.72 +    @BeforeClass
   61.73 +    public static void setUpClass() throws Exception {
   61.74 +        ScriptEngineManager sem = new ScriptEngineManager();
   61.75 +        final ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
   61.76 +        
   61.77 +        final URL my = JsClassLoaderTest.class.getProtectionDomain().getCodeSource().getLocation();
   61.78 +        ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
   61.79 +        final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
   61.80 +        class MyCL extends JsClassLoader implements Fn.Presenter {
   61.81 +
   61.82 +            public MyCL(ClassLoader parent) {
   61.83 +                super(parent);
   61.84 +            }
   61.85 +            
   61.86 +            @Override
   61.87 +            protected URL findResource(String name) {
   61.88 +                return ul.getResource(name);
   61.89 +            }
   61.90 +            @Override
   61.91 +            public Fn defineFn(String code, String... names) {
   61.92 +                StringBuilder sb = new StringBuilder();
   61.93 +                sb.append("(function() {");
   61.94 +                sb.append("return function(");
   61.95 +                String sep = "";
   61.96 +                for (String n : names) {
   61.97 +                    sb.append(sep);
   61.98 +                    sb.append(n);
   61.99 +                    sep = ", ";
  61.100 +                }
  61.101 +                sb.append(") {");
  61.102 +                sb.append(code);
  61.103 +                sb.append("};");
  61.104 +                sb.append("})()");
  61.105 +                try {
  61.106 +                    final Object val = eng.eval(sb.toString());
  61.107 +                    return new Fn(this) {
  61.108 +                        @Override
  61.109 +                        public Object invoke(Object thiz, Object... args) throws Exception {
  61.110 +                            List<Object> all = new ArrayList<Object>(args.length + 1);
  61.111 +                            all.add(thiz == null ? val : thiz);
  61.112 +                            all.addAll(Arrays.asList(args));
  61.113 +                            Invocable inv = (Invocable)eng;
  61.114 +                            try {
  61.115 +                                Object ret = inv.invokeMethod(val, "call", all.toArray());
  61.116 +                                return val.equals(ret) ? null : ret;
  61.117 +                            } catch (Exception ex) {
  61.118 +                                throw ex;
  61.119 +                            }
  61.120 +                        }
  61.121 +                    };
  61.122 +                } catch (ScriptException ex) {
  61.123 +                    throw new LinkageError("Can't parse: " + sb, ex);
  61.124 +                }
  61.125 +            }
  61.126 +
  61.127 +            @Override
  61.128 +            protected Enumeration<URL> findResources(String name) {
  61.129 +                throw new UnsupportedOperationException();
  61.130 +            }
  61.131 +
  61.132 +            @Override
  61.133 +            public void loadScript(Reader code) throws ScriptException {
  61.134 +                eng.eval(code);
  61.135 +            }
  61.136 +
  61.137 +            @Override
  61.138 +            public void displayPage(URL page, Runnable onPageLoad) {
  61.139 +                throw new UnsupportedOperationException();
  61.140 +            }
  61.141 +        };
  61.142 +        
  61.143 +        MyCL l = new MyCL(parent);
  61.144 +        Closeable close = FnContext.activate(l);
  61.145 +        methodClass = l.loadClass(JsMethods.class.getName());
  61.146 +        close.close();
  61.147 +        loader = l;
  61.148 +    }
  61.149 +    
  61.150 +    @BeforeMethod public void initPresenter() {
  61.151 +        FnContext.currentPresenter(loader);
  61.152 +    }
  61.153 +
  61.154 +    @AfterClass
  61.155 +    public static void cleanUp() {
  61.156 +        methodClass = null;
  61.157 +    }
  61.158 +}
  61.159 \ No newline at end of file
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/JsMethods.java	Mon Dec 16 17:16:40 2013 +0100
    62.3 @@ -0,0 +1,129 @@
    62.4 +/**
    62.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    62.6 + *
    62.7 + * Copyright 1997-2010 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 net.java.html.js.JavaScriptBody;
   62.49 +import net.java.html.js.JavaScriptResource;
   62.50 +
   62.51 +
   62.52 +/**
   62.53 + *
   62.54 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   62.55 + */
   62.56 +@JavaScriptResource("jsmethods.js")
   62.57 +public class JsMethods {
   62.58 +    private Object value;
   62.59 +    
   62.60 +    @JavaScriptBody(args = {}, body = "return 42;")
   62.61 +    public static Object fortyTwo() {
   62.62 +        return -42;
   62.63 +    }
   62.64 +    
   62.65 +    @JavaScriptBody(args = {"x", "y" }, body = "return x + y;")
   62.66 +    public static native int plus(int x, int y);
   62.67 +    
   62.68 +    @JavaScriptBody(args = {"x"}, body = "return x;")
   62.69 +    public static native int plus(int x);
   62.70 +    
   62.71 +    @JavaScriptBody(args = {}, body = "return this;")
   62.72 +    public static native Object staticThis();
   62.73 +    
   62.74 +    @JavaScriptBody(args = {}, body = "return this;")
   62.75 +    public native Object getThis();
   62.76 +    @JavaScriptBody(args = {"x"}, body = "return x;")
   62.77 +    public native int plusInst(int x);
   62.78 +    
   62.79 +    @JavaScriptBody(args = {}, body = "return true;")
   62.80 +    public static boolean truth() {
   62.81 +        return false;
   62.82 +    }
   62.83 +    
   62.84 +    @JavaScriptBody(args = { "r" }, javacall=true, body = "r.@java.lang.Runnable::run()();")
   62.85 +    public static native void callback(Runnable r);
   62.86 +    
   62.87 +    @JavaScriptBody(args = { "at", "arr" }, javacall = true, body =
   62.88 +          "var a = 0;\n"
   62.89 +        + "for (var i = 0; i < arr.length; i++) {\n"
   62.90 +        + "  a = at.@org.netbeans.html.boot.impl.Arithm::sumTwo(II)(a, arr[i]);\n"
   62.91 +        + "}\n"
   62.92 +        + "return a;"
   62.93 +    )
   62.94 +    private static native int sumArr(Arithm at, int... arr);
   62.95 +    
   62.96 +    public static int sumArr(int... arr) {
   62.97 +        return sumArr(new Arithm(), arr);
   62.98 +    }
   62.99 +    
  62.100 +    @JavaScriptBody(args = { "x", "y" }, body = "return mul(x, y);")
  62.101 +    public static native int useExternalMul(int x, int y);
  62.102 +    
  62.103 +    @JavaScriptBody(args = { "m" }, javacall = true, body = "return m.@org.netbeans.html.boot.impl.JsMethods::getThis()();")
  62.104 +    public static native JsMethods returnYourSelf(JsMethods m);
  62.105 +    
  62.106 +    @JavaScriptBody(args = { "x", "y" }, javacall = true, body = "return @org.netbeans.html.boot.impl.JsMethods::useExternalMul(II)(x, y);")
  62.107 +    public static native int staticCallback(int x, int y);
  62.108 +
  62.109 +    @JavaScriptBody(args = { "v" }, javacall = true, body = "return @java.lang.Integer::parseInt(Ljava/lang/String;)(v);")
  62.110 +    public static native int parseInt(String v);
  62.111 +    
  62.112 +    @JavaScriptBody(args = { "useA", "useB", "a", "b" }, body = "var l = 0;"
  62.113 +        + "if (useA) l += a;\n"
  62.114 +        + "if (useB) l += b;\n"
  62.115 +        + "return l;\n"
  62.116 +    )
  62.117 +    public static native long chooseLong(boolean useA, boolean useB, long a, long b);
  62.118 +    
  62.119 +    protected void onError(Object o) throws Exception {
  62.120 +        value = o;
  62.121 +    }
  62.122 +    
  62.123 +    Object getError() {
  62.124 +        return value;
  62.125 +    }
  62.126 +    
  62.127 +    @JavaScriptBody(args = { "err" }, javacall = true, body = 
  62.128 +        "this.@org.netbeans.html.boot.impl.JsMethods::onError(Ljava/lang/Object;)(err);"
  62.129 +      + "return this.@org.netbeans.html.boot.impl.JsMethods::getError()();"
  62.130 +    )
  62.131 +    public native Object recordError(Object err);
  62.132 +}
    63.1 --- a/boot/src/test/resources/org/apidesign/html/boot/impl/jsmethods.js	Mon Dec 16 17:16:02 2013 +0100
    63.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.3 @@ -1,22 +0,0 @@
    63.4 -/*
    63.5 - * HTML via Java(tm) Language Bindings
    63.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    63.7 - *
    63.8 - * This program is free software: you can redistribute it and/or modify
    63.9 - * it under the terms of the GNU General Public License as published by
   63.10 - * the Free Software Foundation, version 2 of the License.
   63.11 - *
   63.12 - * This program is distributed in the hope that it will be useful,
   63.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   63.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   63.15 - * GNU General Public License for more details. apidesign.org
   63.16 - * designates this particular file as subject to the
   63.17 - * "Classpath" exception as provided by apidesign.org
   63.18 - * in the License file that accompanied this code.
   63.19 - *
   63.20 - * You should have received a copy of the GNU General Public License
   63.21 - * along with this program. Look for COPYING file in the top folder.
   63.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   63.23 - */
   63.24 -
   63.25 -function mul(x, y) { return x * y; }
    64.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.2 +++ b/boot/src/test/resources/org/netbeans/html/boot/impl/jsmethods.js	Mon Dec 16 17:16:40 2013 +0100
    64.3 @@ -0,0 +1,43 @@
    64.4 +/*
    64.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    64.6 + *
    64.7 + * Copyright 1997-2010 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 +function mul(x, y) { return x * y; }
    65.1 --- a/context/pom.xml	Mon Dec 16 17:16:02 2013 +0100
    65.2 +++ b/context/pom.xml	Mon Dec 16 17:16:40 2013 +0100
    65.3 @@ -2,11 +2,11 @@
    65.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">
    65.5    <modelVersion>4.0.0</modelVersion>
    65.6    <parent>
    65.7 -    <groupId>org.apidesign</groupId>
    65.8 -    <artifactId>html</artifactId>
    65.9 +    <groupId>org.netbeans.html</groupId>
   65.10 +    <artifactId>pom</artifactId>
   65.11      <version>0.7-SNAPSHOT</version>
   65.12    </parent>
   65.13 -  <groupId>org.apidesign.html</groupId>
   65.14 +  <groupId>org.netbeans.html</groupId>
   65.15    <artifactId>net.java.html</artifactId>
   65.16    <version>0.7-SNAPSHOT</version>
   65.17    <packaging>bundle</packaging>
    66.1 --- a/context/src/main/java/net/java/html/BrwsrCtx.java	Mon Dec 16 17:16:02 2013 +0100
    66.2 +++ b/context/src/main/java/net/java/html/BrwsrCtx.java	Mon Dec 16 17:16:40 2013 +0100
    66.3 @@ -1,29 +1,51 @@
    66.4  /**
    66.5 - * HTML via Java(tm) Language Bindings
    66.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    66.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    66.8   *
    66.9 - * This program is free software: you can redistribute it and/or modify
   66.10 - * it under the terms of the GNU General Public License as published by
   66.11 - * the Free Software Foundation, version 2 of the License.
   66.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   66.13   *
   66.14 - * This program is distributed in the hope that it will be useful,
   66.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   66.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   66.17 - * GNU General Public License for more details. apidesign.org
   66.18 - * designates this particular file as subject to the
   66.19 - * "Classpath" exception as provided by apidesign.org
   66.20 - * in the License file that accompanied this code.
   66.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   66.22 + * Other names may be trademarks of their respective owners.
   66.23   *
   66.24 - * You should have received a copy of the GNU General Public License
   66.25 - * along with this program. Look for COPYING file in the top folder.
   66.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   66.27 + * The contents of this file are subject to the terms of either the GNU
   66.28 + * General Public License Version 2 only ("GPL") or the Common
   66.29 + * Development and Distribution License("CDDL") (collectively, the
   66.30 + * "License"). You may not use this file except in compliance with the
   66.31 + * License. You can obtain a copy of the License at
   66.32 + * http://www.netbeans.org/cddl-gplv2.html
   66.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   66.34 + * specific language governing permissions and limitations under the
   66.35 + * License.  When distributing the software, include this License Header
   66.36 + * Notice in each file and include the License file at
   66.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   66.38 + * particular file as subject to the "Classpath" exception as provided
   66.39 + * by Oracle in the GPL Version 2 section of the License file that
   66.40 + * accompanied this code. If applicable, add the following below the
   66.41 + * License Header, with the fields enclosed by brackets [] replaced by
   66.42 + * your own identifying information:
   66.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   66.44 + *
   66.45 + * Contributor(s):
   66.46 + *
   66.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   66.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   66.49 + *
   66.50 + * If you wish your version of this file to be governed by only the CDDL
   66.51 + * or only the GPL Version 2, indicate your decision by adding
   66.52 + * "[Contributor] elects to include this software in this distribution
   66.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   66.54 + * single choice of license, a recipient has the option to distribute
   66.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   66.56 + * to extend the choice of license to its licensees as provided above.
   66.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   66.58 + * Version 2 license, then the option applies only if the new code is
   66.59 + * made subject to such option by the copyright holder.
   66.60   */
   66.61  package net.java.html;
   66.62  
   66.63  import java.util.ServiceLoader;
   66.64  import java.util.logging.Logger;
   66.65 -import org.apidesign.html.context.impl.CtxAccssr;
   66.66 -import org.apidesign.html.context.impl.CtxImpl;
   66.67 +import org.netbeans.html.context.impl.CtxAccssr;
   66.68 +import org.netbeans.html.context.impl.CtxImpl;
   66.69  import org.apidesign.html.context.spi.Contexts;
   66.70  
   66.71  /** Represents context where the <code>net.java.html.json.Model</code>
    67.1 --- a/context/src/main/java/org/apidesign/html/context/impl/CtxAccssr.java	Mon Dec 16 17:16:02 2013 +0100
    67.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    67.3 @@ -1,52 +0,0 @@
    67.4 -/**
    67.5 - * HTML via Java(tm) Language Bindings
    67.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    67.7 - *
    67.8 - * This program is free software: you can redistribute it and/or modify
    67.9 - * it under the terms of the GNU General Public License as published by
   67.10 - * the Free Software Foundation, version 2 of the License.
   67.11 - *
   67.12 - * This program is distributed in the hope that it will be useful,
   67.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   67.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   67.15 - * GNU General Public License for more details. apidesign.org
   67.16 - * designates this particular file as subject to the
   67.17 - * "Classpath" exception as provided by apidesign.org
   67.18 - * in the License file that accompanied this code.
   67.19 - *
   67.20 - * You should have received a copy of the GNU General Public License
   67.21 - * along with this program. Look for COPYING file in the top folder.
   67.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   67.23 - */
   67.24 -package org.apidesign.html.context.impl;
   67.25 -
   67.26 -import net.java.html.BrwsrCtx;
   67.27 -
   67.28 -/** Internal communication between API (e.g. {@link BrwsrCtx}), SPI
   67.29 - * (e.g. {@link ContextBuilder}) and the implementation package.
   67.30 - *
   67.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   67.32 - */
   67.33 -public abstract class CtxAccssr {
   67.34 -    private static CtxAccssr DEFAULT;
   67.35 -    static {
   67.36 -        // run initializers
   67.37 -        try {
   67.38 -            BrwsrCtx.EMPTY.getClass();
   67.39 -        } catch (NullPointerException ex) {
   67.40 -            // ignore
   67.41 -        }
   67.42 -    }
   67.43 -    
   67.44 -    protected CtxAccssr() {
   67.45 -        if (DEFAULT != null) throw new IllegalStateException();
   67.46 -        DEFAULT = this;
   67.47 -    }
   67.48 -    
   67.49 -    protected abstract BrwsrCtx newContext(CtxImpl impl);
   67.50 -    protected abstract CtxImpl find(BrwsrCtx context);
   67.51 -    
   67.52 -    static CtxAccssr getDefault() {
   67.53 -        return DEFAULT;
   67.54 -    }
   67.55 -}
    68.1 --- a/context/src/main/java/org/apidesign/html/context/impl/CtxImpl.java	Mon Dec 16 17:16:02 2013 +0100
    68.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    68.3 @@ -1,88 +0,0 @@
    68.4 -/**
    68.5 - * HTML via Java(tm) Language Bindings
    68.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    68.7 - *
    68.8 - * This program is free software: you can redistribute it and/or modify
    68.9 - * it under the terms of the GNU General Public License as published by
   68.10 - * the Free Software Foundation, version 2 of the License.
   68.11 - *
   68.12 - * This program is distributed in the hope that it will be useful,
   68.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   68.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   68.15 - * GNU General Public License for more details. apidesign.org
   68.16 - * designates this particular file as subject to the
   68.17 - * "Classpath" exception as provided by apidesign.org
   68.18 - * in the License file that accompanied this code.
   68.19 - *
   68.20 - * You should have received a copy of the GNU General Public License
   68.21 - * along with this program. Look for COPYING file in the top folder.
   68.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   68.23 - */
   68.24 -package org.apidesign.html.context.impl;
   68.25 -
   68.26 -import java.util.ArrayList;
   68.27 -import java.util.Collections;
   68.28 -import java.util.List;
   68.29 -import net.java.html.BrwsrCtx;
   68.30 -
   68.31 -/** Implementation detail. Holds list of technologies for particular
   68.32 - * {@link BrwsrCtx}.
   68.33 - *
   68.34 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   68.35 - */
   68.36 -public final class CtxImpl {
   68.37 -    private final List<Bind<?>> techs;
   68.38 -    
   68.39 -    public CtxImpl() {
   68.40 -        techs = new ArrayList<Bind<?>>();
   68.41 -    }
   68.42 -    
   68.43 -    private CtxImpl(List<Bind<?>> techs) {
   68.44 -        this.techs = techs;
   68.45 -    }
   68.46 -    
   68.47 -    public static <Tech> Tech find(BrwsrCtx context, Class<Tech> technology) {
   68.48 -        CtxImpl impl = CtxAccssr.getDefault().find(context);
   68.49 -        for (Bind<?> bind : impl.techs) {
   68.50 -            if (technology == bind.clazz) {
   68.51 -                return technology.cast(bind.impl);
   68.52 -            }
   68.53 -        }
   68.54 -        return null;
   68.55 -    }
   68.56 -
   68.57 -    public BrwsrCtx build() {
   68.58 -        Collections.sort(techs);
   68.59 -        CtxImpl impl = new CtxImpl(Collections.unmodifiableList(techs));
   68.60 -        return CtxAccssr.getDefault().newContext(impl);
   68.61 -    }
   68.62 -
   68.63 -    public <Tech> void register(Class<Tech> type, Tech impl, int priority) {
   68.64 -        techs.add(new Bind<Tech>(type, impl, priority));
   68.65 -    }
   68.66 -    
   68.67 -    private static final class Bind<Tech> implements Comparable<Bind<?>> {
   68.68 -        private final Class<Tech> clazz;
   68.69 -        private final Tech impl;
   68.70 -        private final int priority;
   68.71 -
   68.72 -        public Bind(Class<Tech> clazz, Tech impl, int priority) {
   68.73 -            this.clazz = clazz;
   68.74 -            this.impl = impl;
   68.75 -            this.priority = priority;
   68.76 -        }
   68.77 -
   68.78 -        @Override
   68.79 -        public int compareTo(Bind<?> o) {
   68.80 -            if (priority != o.priority) {
   68.81 -                return priority - o.priority;
   68.82 -            }
   68.83 -            return clazz.getName().compareTo(o.clazz.getName());
   68.84 -        }
   68.85 -
   68.86 -        @Override
   68.87 -        public String toString() {
   68.88 -            return "Bind{" + "clazz=" + clazz + "@" + clazz.getClassLoader() + ", impl=" + impl + ", priority=" + priority + '}';
   68.89 -        }
   68.90 -    }
   68.91 -}
    69.1 --- a/context/src/main/java/org/apidesign/html/context/spi/Contexts.java	Mon Dec 16 17:16:02 2013 +0100
    69.2 +++ b/context/src/main/java/org/apidesign/html/context/spi/Contexts.java	Mon Dec 16 17:16:40 2013 +0100
    69.3 @@ -1,27 +1,49 @@
    69.4  /**
    69.5 - * HTML via Java(tm) Language Bindings
    69.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    69.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    69.8   *
    69.9 - * This program is free software: you can redistribute it and/or modify
   69.10 - * it under the terms of the GNU General Public License as published by
   69.11 - * the Free Software Foundation, version 2 of the License.
   69.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   69.13   *
   69.14 - * This program is distributed in the hope that it will be useful,
   69.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   69.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   69.17 - * GNU General Public License for more details. apidesign.org
   69.18 - * designates this particular file as subject to the
   69.19 - * "Classpath" exception as provided by apidesign.org
   69.20 - * in the License file that accompanied this code.
   69.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   69.22 + * Other names may be trademarks of their respective owners.
   69.23   *
   69.24 - * You should have received a copy of the GNU General Public License
   69.25 - * along with this program. Look for COPYING file in the top folder.
   69.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   69.27 + * The contents of this file are subject to the terms of either the GNU
   69.28 + * General Public License Version 2 only ("GPL") or the Common
   69.29 + * Development and Distribution License("CDDL") (collectively, the
   69.30 + * "License"). You may not use this file except in compliance with the
   69.31 + * License. You can obtain a copy of the License at
   69.32 + * http://www.netbeans.org/cddl-gplv2.html
   69.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   69.34 + * specific language governing permissions and limitations under the
   69.35 + * License.  When distributing the software, include this License Header
   69.36 + * Notice in each file and include the License file at
   69.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   69.38 + * particular file as subject to the "Classpath" exception as provided
   69.39 + * by Oracle in the GPL Version 2 section of the License file that
   69.40 + * accompanied this code. If applicable, add the following below the
   69.41 + * License Header, with the fields enclosed by brackets [] replaced by
   69.42 + * your own identifying information:
   69.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   69.44 + *
   69.45 + * Contributor(s):
   69.46 + *
   69.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   69.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   69.49 + *
   69.50 + * If you wish your version of this file to be governed by only the CDDL
   69.51 + * or only the GPL Version 2, indicate your decision by adding
   69.52 + * "[Contributor] elects to include this software in this distribution
   69.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   69.54 + * single choice of license, a recipient has the option to distribute
   69.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   69.56 + * to extend the choice of license to its licensees as provided above.
   69.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   69.58 + * Version 2 license, then the option applies only if the new code is
   69.59 + * made subject to such option by the copyright holder.
   69.60   */
   69.61  package org.apidesign.html.context.spi;
   69.62  
   69.63  import net.java.html.BrwsrCtx;
   69.64 -import org.apidesign.html.context.impl.CtxImpl;
   69.65 +import org.netbeans.html.context.impl.CtxImpl;
   69.66  
   69.67  /**
   69.68   *
    70.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.2 +++ b/context/src/main/java/org/netbeans/html/context/impl/CtxAccssr.java	Mon Dec 16 17:16:40 2013 +0100
    70.3 @@ -0,0 +1,74 @@
    70.4 +/**
    70.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    70.6 + *
    70.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    70.8 + *
    70.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   70.10 + * Other names may be trademarks of their respective owners.
   70.11 + *
   70.12 + * The contents of this file are subject to the terms of either the GNU
   70.13 + * General Public License Version 2 only ("GPL") or the Common
   70.14 + * Development and Distribution License("CDDL") (collectively, the
   70.15 + * "License"). You may not use this file except in compliance with the
   70.16 + * License. You can obtain a copy of the License at
   70.17 + * http://www.netbeans.org/cddl-gplv2.html
   70.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   70.19 + * specific language governing permissions and limitations under the
   70.20 + * License.  When distributing the software, include this License Header
   70.21 + * Notice in each file and include the License file at
   70.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   70.23 + * particular file as subject to the "Classpath" exception as provided
   70.24 + * by Oracle in the GPL Version 2 section of the License file that
   70.25 + * accompanied this code. If applicable, add the following below the
   70.26 + * License Header, with the fields enclosed by brackets [] replaced by
   70.27 + * your own identifying information:
   70.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   70.29 + *
   70.30 + * Contributor(s):
   70.31 + *
   70.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   70.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   70.34 + *
   70.35 + * If you wish your version of this file to be governed by only the CDDL
   70.36 + * or only the GPL Version 2, indicate your decision by adding
   70.37 + * "[Contributor] elects to include this software in this distribution
   70.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   70.39 + * single choice of license, a recipient has the option to distribute
   70.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   70.41 + * to extend the choice of license to its licensees as provided above.
   70.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   70.43 + * Version 2 license, then the option applies only if the new code is
   70.44 + * made subject to such option by the copyright holder.
   70.45 + */
   70.46 +package org.netbeans.html.context.impl;
   70.47 +
   70.48 +import net.java.html.BrwsrCtx;
   70.49 +
   70.50 +/** Internal communication between API (e.g. {@link BrwsrCtx}), SPI
   70.51 + * (e.g. {@link ContextBuilder}) and the implementation package.
   70.52 + *
   70.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   70.54 + */
   70.55 +public abstract class CtxAccssr {
   70.56 +    private static CtxAccssr DEFAULT;
   70.57 +    static {
   70.58 +        // run initializers
   70.59 +        try {
   70.60 +            BrwsrCtx.EMPTY.getClass();
   70.61 +        } catch (NullPointerException ex) {
   70.62 +            // ignore
   70.63 +        }
   70.64 +    }
   70.65 +    
   70.66 +    protected CtxAccssr() {
   70.67 +        if (DEFAULT != null) throw new IllegalStateException();
   70.68 +        DEFAULT = this;
   70.69 +    }
   70.70 +    
   70.71 +    protected abstract BrwsrCtx newContext(CtxImpl impl);
   70.72 +    protected abstract CtxImpl find(BrwsrCtx context);
   70.73 +    
   70.74 +    static CtxAccssr getDefault() {
   70.75 +        return DEFAULT;
   70.76 +    }
   70.77 +}
    71.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    71.2 +++ b/context/src/main/java/org/netbeans/html/context/impl/CtxImpl.java	Mon Dec 16 17:16:40 2013 +0100
    71.3 @@ -0,0 +1,110 @@
    71.4 +/**
    71.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    71.6 + *
    71.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    71.8 + *
    71.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   71.10 + * Other names may be trademarks of their respective owners.
   71.11 + *
   71.12 + * The contents of this file are subject to the terms of either the GNU
   71.13 + * General Public License Version 2 only ("GPL") or the Common
   71.14 + * Development and Distribution License("CDDL") (collectively, the
   71.15 + * "License"). You may not use this file except in compliance with the
   71.16 + * License. You can obtain a copy of the License at
   71.17 + * http://www.netbeans.org/cddl-gplv2.html
   71.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   71.19 + * specific language governing permissions and limitations under the
   71.20 + * License.  When distributing the software, include this License Header
   71.21 + * Notice in each file and include the License file at
   71.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   71.23 + * particular file as subject to the "Classpath" exception as provided
   71.24 + * by Oracle in the GPL Version 2 section of the License file that
   71.25 + * accompanied this code. If applicable, add the following below the
   71.26 + * License Header, with the fields enclosed by brackets [] replaced by
   71.27 + * your own identifying information:
   71.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   71.29 + *
   71.30 + * Contributor(s):
   71.31 + *
   71.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   71.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   71.34 + *
   71.35 + * If you wish your version of this file to be governed by only the CDDL
   71.36 + * or only the GPL Version 2, indicate your decision by adding
   71.37 + * "[Contributor] elects to include this software in this distribution
   71.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   71.39 + * single choice of license, a recipient has the option to distribute
   71.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   71.41 + * to extend the choice of license to its licensees as provided above.
   71.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   71.43 + * Version 2 license, then the option applies only if the new code is
   71.44 + * made subject to such option by the copyright holder.
   71.45 + */
   71.46 +package org.netbeans.html.context.impl;
   71.47 +
   71.48 +import java.util.ArrayList;
   71.49 +import java.util.Collections;
   71.50 +import java.util.List;
   71.51 +import net.java.html.BrwsrCtx;
   71.52 +
   71.53 +/** Implementation detail. Holds list of technologies for particular
   71.54 + * {@link BrwsrCtx}.
   71.55 + *
   71.56 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   71.57 + */
   71.58 +public final class CtxImpl {
   71.59 +    private final List<Bind<?>> techs;
   71.60 +    
   71.61 +    public CtxImpl() {
   71.62 +        techs = new ArrayList<Bind<?>>();
   71.63 +    }
   71.64 +    
   71.65 +    private CtxImpl(List<Bind<?>> techs) {
   71.66 +        this.techs = techs;
   71.67 +    }
   71.68 +    
   71.69 +    public static <Tech> Tech find(BrwsrCtx context, Class<Tech> technology) {
   71.70 +        CtxImpl impl = CtxAccssr.getDefault().find(context);
   71.71 +        for (Bind<?> bind : impl.techs) {
   71.72 +            if (technology == bind.clazz) {
   71.73 +                return technology.cast(bind.impl);
   71.74 +            }
   71.75 +        }
   71.76 +        return null;
   71.77 +    }
   71.78 +
   71.79 +    public BrwsrCtx build() {
   71.80 +        Collections.sort(techs);
   71.81 +        CtxImpl impl = new CtxImpl(Collections.unmodifiableList(techs));
   71.82 +        return CtxAccssr.getDefault().newContext(impl);
   71.83 +    }
   71.84 +
   71.85 +    public <Tech> void register(Class<Tech> type, Tech impl, int priority) {
   71.86 +        techs.add(new Bind<Tech>(type, impl, priority));
   71.87 +    }
   71.88 +    
   71.89 +    private static final class Bind<Tech> implements Comparable<Bind<?>> {
   71.90 +        private final Class<Tech> clazz;
   71.91 +        private final Tech impl;
   71.92 +        private final int priority;
   71.93 +
   71.94 +        public Bind(Class<Tech> clazz, Tech impl, int priority) {
   71.95 +            this.clazz = clazz;
   71.96 +            this.impl = impl;
   71.97 +            this.priority = priority;
   71.98 +        }
   71.99 +
  71.100 +        @Override
  71.101 +        public int compareTo(Bind<?> o) {
  71.102 +            if (priority != o.priority) {
  71.103 +                return priority - o.priority;
  71.104 +            }
  71.105 +            return clazz.getName().compareTo(o.clazz.getName());
  71.106 +        }
  71.107 +
  71.108 +        @Override
  71.109 +        public String toString() {
  71.110 +            return "Bind{" + "clazz=" + clazz + "@" + clazz.getClassLoader() + ", impl=" + impl + ", priority=" + priority + '}';
  71.111 +        }
  71.112 +    }
  71.113 +}
    72.1 --- a/geo/pom.xml	Mon Dec 16 17:16:02 2013 +0100
    72.2 +++ b/geo/pom.xml	Mon Dec 16 17:16:40 2013 +0100
    72.3 @@ -2,11 +2,11 @@
    72.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">
    72.5    <modelVersion>4.0.0</modelVersion>
    72.6    <parent>
    72.7 -    <groupId>org.apidesign</groupId>
    72.8 -    <artifactId>html</artifactId>
    72.9 +    <groupId>org.netbeans.html</groupId>
   72.10 +    <artifactId>pom</artifactId>
   72.11      <version>0.7-SNAPSHOT</version>
   72.12    </parent>
   72.13 -  <groupId>org.apidesign.html</groupId>
   72.14 +  <groupId>org.netbeans.html</groupId>
   72.15    <artifactId>net.java.html.geo</artifactId>
   72.16    <version>0.7-SNAPSHOT</version>
   72.17    <packaging>bundle</packaging>
   72.18 @@ -35,7 +35,7 @@
   72.19        <type>jar</type>
   72.20      </dependency>
   72.21      <dependency>
   72.22 -      <groupId>org.apidesign.html</groupId>
   72.23 +      <groupId>org.netbeans.html</groupId>
   72.24        <artifactId>net.java.html.boot</artifactId>
   72.25        <version>${project.version}</version>
   72.26        <type>jar</type>
    73.1 --- a/geo/src/main/java/net/java/html/geo/OnLocation.java	Mon Dec 16 17:16:02 2013 +0100
    73.2 +++ b/geo/src/main/java/net/java/html/geo/OnLocation.java	Mon Dec 16 17:16:40 2013 +0100
    73.3 @@ -1,22 +1,44 @@
    73.4  /**
    73.5 - * HTML via Java(tm) Language Bindings
    73.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    73.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    73.8   *
    73.9 - * This program is free software: you can redistribute it and/or modify
   73.10 - * it under the terms of the GNU General Public License as published by
   73.11 - * the Free Software Foundation, version 2 of the License.
   73.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   73.13   *
   73.14 - * This program is distributed in the hope that it will be useful,
   73.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   73.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   73.17 - * GNU General Public License for more details. apidesign.org
   73.18 - * designates this particular file as subject to the
   73.19 - * "Classpath" exception as provided by apidesign.org
   73.20 - * in the License file that accompanied this code.
   73.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   73.22 + * Other names may be trademarks of their respective owners.
   73.23   *
   73.24 - * You should have received a copy of the GNU General Public License
   73.25 - * along with this program. Look for COPYING file in the top folder.
   73.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   73.27 + * The contents of this file are subject to the terms of either the GNU
   73.28 + * General Public License Version 2 only ("GPL") or the Common
   73.29 + * Development and Distribution License("CDDL") (collectively, the
   73.30 + * "License"). You may not use this file except in compliance with the
   73.31 + * License. You can obtain a copy of the License at
   73.32 + * http://www.netbeans.org/cddl-gplv2.html
   73.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   73.34 + * specific language governing permissions and limitations under the
   73.35 + * License.  When distributing the software, include this License Header
   73.36 + * Notice in each file and include the License file at
   73.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   73.38 + * particular file as subject to the "Classpath" exception as provided
   73.39 + * by Oracle in the GPL Version 2 section of the License file that
   73.40 + * accompanied this code. If applicable, add the following below the
   73.41 + * License Header, with the fields enclosed by brackets [] replaced by
   73.42 + * your own identifying information:
   73.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   73.44 + *
   73.45 + * Contributor(s):
   73.46 + *
   73.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   73.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   73.49 + *
   73.50 + * If you wish your version of this file to be governed by only the CDDL
   73.51 + * or only the GPL Version 2, indicate your decision by adding
   73.52 + * "[Contributor] elects to include this software in this distribution
   73.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   73.54 + * single choice of license, a recipient has the option to distribute
   73.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   73.56 + * to extend the choice of license to its licensees as provided above.
   73.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   73.58 + * Version 2 license, then the option applies only if the new code is
   73.59 + * made subject to such option by the copyright holder.
   73.60   */
   73.61  package net.java.html.geo;
   73.62  
    74.1 --- a/geo/src/main/java/net/java/html/geo/Position.java	Mon Dec 16 17:16:02 2013 +0100
    74.2 +++ b/geo/src/main/java/net/java/html/geo/Position.java	Mon Dec 16 17:16:40 2013 +0100
    74.3 @@ -1,28 +1,50 @@
    74.4  /**
    74.5 - * HTML via Java(tm) Language Bindings
    74.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    74.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    74.8   *
    74.9 - * This program is free software: you can redistribute it and/or modify
   74.10 - * it under the terms of the GNU General Public License as published by
   74.11 - * the Free Software Foundation, version 2 of the License.
   74.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   74.13   *
   74.14 - * This program is distributed in the hope that it will be useful,
   74.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   74.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   74.17 - * GNU General Public License for more details. apidesign.org
   74.18 - * designates this particular file as subject to the
   74.19 - * "Classpath" exception as provided by apidesign.org
   74.20 - * in the License file that accompanied this code.
   74.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   74.22 + * Other names may be trademarks of their respective owners.
   74.23   *
   74.24 - * You should have received a copy of the GNU General Public License
   74.25 - * along with this program. Look for COPYING file in the top folder.
   74.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   74.27 + * The contents of this file are subject to the terms of either the GNU
   74.28 + * General Public License Version 2 only ("GPL") or the Common
   74.29 + * Development and Distribution License("CDDL") (collectively, the
   74.30 + * "License"). You may not use this file except in compliance with the
   74.31 + * License. You can obtain a copy of the License at
   74.32 + * http://www.netbeans.org/cddl-gplv2.html
   74.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   74.34 + * specific language governing permissions and limitations under the
   74.35 + * License.  When distributing the software, include this License Header
   74.36 + * Notice in each file and include the License file at
   74.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   74.38 + * particular file as subject to the "Classpath" exception as provided
   74.39 + * by Oracle in the GPL Version 2 section of the License file that
   74.40 + * accompanied this code. If applicable, add the following below the
   74.41 + * License Header, with the fields enclosed by brackets [] replaced by
   74.42 + * your own identifying information:
   74.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   74.44 + *
   74.45 + * Contributor(s):
   74.46 + *
   74.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   74.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   74.49 + *
   74.50 + * If you wish your version of this file to be governed by only the CDDL
   74.51 + * or only the GPL Version 2, indicate your decision by adding
   74.52 + * "[Contributor] elects to include this software in this distribution
   74.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   74.54 + * single choice of license, a recipient has the option to distribute
   74.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   74.56 + * to extend the choice of license to its licensees as provided above.
   74.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   74.58 + * Version 2 license, then the option applies only if the new code is
   74.59 + * made subject to such option by the copyright holder.
   74.60   */
   74.61  package net.java.html.geo;
   74.62  
   74.63  import java.util.logging.Level;
   74.64  import java.util.logging.Logger;
   74.65 -import org.apidesign.html.geo.impl.JsG;
   74.66 +import org.netbeans.html.geo.impl.JsG;
   74.67  
   74.68  /** Class that represents a geolocation position provided as a callback
   74.69   * to {@link Handle#onLocation(net.java.html.geo.Position)} method. The
    75.1 --- a/geo/src/main/java/net/java/html/geo/package.html	Mon Dec 16 17:16:02 2013 +0100
    75.2 +++ b/geo/src/main/java/net/java/html/geo/package.html	Mon Dec 16 17:16:40 2013 +0100
    75.3 @@ -1,23 +1,45 @@
    75.4  <!--
    75.5  
    75.6 -    HTML via Java(tm) Language Bindings
    75.7 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    75.8 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    75.9  
   75.10 -    This program is free software: you can redistribute it and/or modify
   75.11 -    it under the terms of the GNU General Public License as published by
   75.12 -    the Free Software Foundation, version 2 of the License.
   75.13 +    Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   75.14  
   75.15 -    This program is distributed in the hope that it will be useful,
   75.16 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   75.17 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   75.18 -    GNU General Public License for more details. apidesign.org
   75.19 -    designates this particular file as subject to the
   75.20 -    "Classpath" exception as provided by apidesign.org
   75.21 -    in the License file that accompanied this code.
   75.22 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   75.23 +    Other names may be trademarks of their respective owners.
   75.24  
   75.25 -    You should have received a copy of the GNU General Public License
   75.26 -    along with this program. Look for COPYING file in the top folder.
   75.27 -    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   75.28 +    The contents of this file are subject to the terms of either the GNU
   75.29 +    General Public License Version 2 only ("GPL") or the Common
   75.30 +    Development and Distribution License("CDDL") (collectively, the
   75.31 +    "License"). You may not use this file except in compliance with the
   75.32 +    License. You can obtain a copy of the License at
   75.33 +    http://www.netbeans.org/cddl-gplv2.html
   75.34 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   75.35 +    specific language governing permissions and limitations under the
   75.36 +    License.  When distributing the software, include this License Header
   75.37 +    Notice in each file and include the License file at
   75.38 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   75.39 +    particular file as subject to the "Classpath" exception as provided
   75.40 +    by Oracle in the GPL Version 2 section of the License file that
   75.41 +    accompanied this code. If applicable, add the following below the
   75.42 +    License Header, with the fields enclosed by brackets [] replaced by
   75.43 +    your own identifying information:
   75.44 +    "Portions Copyrighted [year] [name of copyright owner]"
   75.45 +
   75.46 +    Contributor(s):
   75.47 +
   75.48 +    The Original Software is NetBeans. The Initial Developer of the Original
   75.49 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   75.50 +
   75.51 +    If you wish your version of this file to be governed by only the CDDL
   75.52 +    or only the GPL Version 2, indicate your decision by adding
   75.53 +    "[Contributor] elects to include this software in this distribution
   75.54 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
   75.55 +    single choice of license, a recipient has the option to distribute
   75.56 +    your version of this file under either the CDDL, the GPL Version 2 or
   75.57 +    to extend the choice of license to its licensees as provided above.
   75.58 +    However, if you add GPL Version 2 code and therefore, elected the GPL
   75.59 +    Version 2 license, then the option applies only if the new code is
   75.60 +    made subject to such option by the copyright holder.
   75.61  
   75.62  -->
   75.63  <!DOCTYPE html>
    76.1 --- a/geo/src/main/java/org/apidesign/html/geo/impl/GeoProcessor.java	Mon Dec 16 17:16:02 2013 +0100
    76.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.3 @@ -1,267 +0,0 @@
    76.4 -/**
    76.5 - * HTML via Java(tm) Language Bindings
    76.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    76.7 - *
    76.8 - * This program is free software: you can redistribute it and/or modify
    76.9 - * it under the terms of the GNU General Public License as published by
   76.10 - * the Free Software Foundation, version 2 of the License.
   76.11 - *
   76.12 - * This program is distributed in the hope that it will be useful,
   76.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   76.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   76.15 - * GNU General Public License for more details. apidesign.org
   76.16 - * designates this particular file as subject to the
   76.17 - * "Classpath" exception as provided by apidesign.org
   76.18 - * in the License file that accompanied this code.
   76.19 - *
   76.20 - * You should have received a copy of the GNU General Public License
   76.21 - * along with this program. Look for COPYING file in the top folder.
   76.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   76.23 - */
   76.24 -package org.apidesign.html.geo.impl;
   76.25 -
   76.26 -import java.io.IOException;
   76.27 -import java.io.Writer;
   76.28 -import java.util.List;
   76.29 -import java.util.Locale;
   76.30 -import java.util.Set;
   76.31 -import java.util.logging.Level;
   76.32 -import java.util.logging.Logger;
   76.33 -import javax.annotation.processing.AbstractProcessor;
   76.34 -import javax.annotation.processing.Processor;
   76.35 -import javax.annotation.processing.RoundEnvironment;
   76.36 -import javax.annotation.processing.SupportedAnnotationTypes;
   76.37 -import javax.annotation.processing.SupportedSourceVersion;
   76.38 -import javax.lang.model.SourceVersion;
   76.39 -import javax.lang.model.element.Element;
   76.40 -import javax.lang.model.element.ElementKind;
   76.41 -import javax.lang.model.element.ExecutableElement;
   76.42 -import javax.lang.model.element.Modifier;
   76.43 -import javax.lang.model.element.PackageElement;
   76.44 -import javax.lang.model.element.TypeElement;
   76.45 -import javax.lang.model.element.VariableElement;
   76.46 -import javax.lang.model.type.TypeMirror;
   76.47 -import javax.tools.Diagnostic;
   76.48 -import javax.tools.JavaFileObject;
   76.49 -import net.java.html.geo.OnLocation;
   76.50 -import net.java.html.geo.Position;
   76.51 -import org.openide.util.lookup.ServiceProvider;
   76.52 -
   76.53 -/** Annotation processor to generate callbacks from {@link GeoHandle} class.
   76.54 - *
   76.55 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   76.56 - */
   76.57 -@ServiceProvider(service=Processor.class)
   76.58 -@SupportedSourceVersion(SourceVersion.RELEASE_6)
   76.59 -@SupportedAnnotationTypes({
   76.60 -    "net.java.html.geo.OnLocation"
   76.61 -})
   76.62 -public final class GeoProcessor extends AbstractProcessor {
   76.63 -    private static final Logger LOG = Logger.getLogger(GeoProcessor.class.getName());
   76.64 -    @Override
   76.65 -    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
   76.66 -        boolean ok = true;
   76.67 -        for (Element e : roundEnv.getElementsAnnotatedWith(OnLocation.class)) {
   76.68 -            if (!processLocation(e)) {
   76.69 -                ok = false;
   76.70 -            }
   76.71 -        }
   76.72 -        return ok;
   76.73 -    }
   76.74 -
   76.75 -    private void error(String msg, Element e) {
   76.76 -        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e);
   76.77 -    }
   76.78 -    
   76.79 -    private boolean processLocation(Element e) {
   76.80 -        if (e.getKind() != ElementKind.METHOD) {
   76.81 -            return false;
   76.82 -        }
   76.83 -        ExecutableElement me = (ExecutableElement) e;
   76.84 -        OnLocation ol = e.getAnnotation(OnLocation.class);
   76.85 -        if (ol == null) {
   76.86 -            return true;
   76.87 -        }
   76.88 -        if (me.getModifiers().contains(Modifier.PRIVATE)) {
   76.89 -            error("Method annotated by @OnLocation cannot be private", e);
   76.90 -            return false;
   76.91 -        }
   76.92 -        TypeMirror positionClass = processingEnv.getElementUtils().getTypeElement(Position.class.getName()).asType();
   76.93 -        final List<? extends VariableElement> params = me.getParameters();
   76.94 -        if (params.size() < 1 || !params.get(0).asType().equals(positionClass)) {
   76.95 -            error("Method annotated by @OnLocation first argument must be net.java.html.geo.Position!", e);
   76.96 -            return false;
   76.97 -        }
   76.98 -        String className = ol.className();
   76.99 -        if (className.isEmpty()) {
  76.100 -            String n = e.getSimpleName().toString();
  76.101 -            if (n.isEmpty()) {
  76.102 -                error("Empty method name", e);
  76.103 -                return false;
  76.104 -            }
  76.105 -            final String firstLetter = n.substring(0, 1).toUpperCase(Locale.ENGLISH);
  76.106 -            className = firstLetter + n.substring(1) + "Handle";
  76.107 -        }
  76.108 -        TypeElement te = (TypeElement)e.getEnclosingElement();
  76.109 -        PackageElement pe = (PackageElement) te.getEnclosingElement();
  76.110 -        final String pkg = pe.getQualifiedName().toString();
  76.111 -        final String fqn = pkg + "." + className;
  76.112 -        final boolean isStatic = me.getModifiers().contains(Modifier.STATIC);
  76.113 -        String sep;
  76.114 -        try {
  76.115 -            JavaFileObject fo = processingEnv.getFiler().createSourceFile(fqn, e);
  76.116 -            Writer w = fo.openWriter();
  76.117 -            w.append("package ").append(pkg).append(";\n");
  76.118 -            w.append("class ").append(className).append(" extends net.java.html.geo.Position.Handle {\n");
  76.119 -            if (!isStatic) {
  76.120 -                w.append("  private final ").append(te.getSimpleName()).append(" $i;\n");
  76.121 -            }
  76.122 -            for (int i = 1; i < params.size(); i++) {
  76.123 -                final VariableElement p = params.get(i);
  76.124 -                w.append("  private final ").append(p.asType().toString()).append(" ").append(p.getSimpleName()).append(";\n");
  76.125 -            }
  76.126 -            w.append("  private ").append(className).append("(boolean oneTime");
  76.127 -            w.append(", ").append(te.getSimpleName()).append(" i");
  76.128 -            for (int i = 1; i < params.size(); i++) {
  76.129 -                final VariableElement p = params.get(i);
  76.130 -                w.append(", ").append(p.asType().toString()).append(" ").append(p.getSimpleName());
  76.131 -            }
  76.132 -            w.append(") {\n    super(oneTime);\n");
  76.133 -            if (!isStatic) {
  76.134 -                w.append("    this.$i = i;\n");
  76.135 -            }
  76.136 -            for (int i = 1; i < params.size(); i++) {
  76.137 -                final VariableElement p = params.get(i);
  76.138 -                w.append("  this.").append(p.getSimpleName()).append(" = ").append(p.getSimpleName()).append(";\n");
  76.139 -            }
  76.140 -            w.append("}\n");
  76.141 -            w.append("  static net.java.html.geo.Position.Handle createQuery(");
  76.142 -            String inst;
  76.143 -            if (!isStatic) {
  76.144 -                w.append(te.getSimpleName()).append(" instance");
  76.145 -                inst = "instance";
  76.146 -                sep = ", ";
  76.147 -            } else {
  76.148 -                inst = "null";
  76.149 -                sep = "";
  76.150 -            }
  76.151 -            for (int i = 1; i < params.size(); i++) {
  76.152 -                final VariableElement p = params.get(i);
  76.153 -                w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName());
  76.154 -                sep = ", ";
  76.155 -            }
  76.156 -            w.append(") { return new ").append(className).append("(true, ").append(inst);
  76.157 -            for (int i = 1; i < params.size(); i++) {
  76.158 -                final VariableElement p = params.get(i);
  76.159 -                w.append(", ").append(p.getSimpleName());
  76.160 -            }
  76.161 -            w.append("); }\n");
  76.162 -            w.append("  static net.java.html.geo.Position.Handle createWatch(");
  76.163 -            if (!isStatic) {
  76.164 -                w.append(te.getSimpleName()).append(" instance");
  76.165 -                sep = ", ";
  76.166 -            } else {
  76.167 -                sep = "";
  76.168 -            }
  76.169 -            for (int i = 1; i < params.size(); i++) {
  76.170 -                final VariableElement p = params.get(i);
  76.171 -                w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName());
  76.172 -            }
  76.173 -            w.append(") { return new ").append(className).append("(false, ").append(inst);
  76.174 -            for (int i = 1; i < params.size(); i++) {
  76.175 -                final VariableElement p = params.get(i);
  76.176 -                w.append(", ").append(p.getSimpleName());
  76.177 -            }
  76.178 -            w.append("); }\n");
  76.179 -            w.append("  @Override protected void onError(Exception t) throws Throwable {\n");
  76.180 -            if (ol.onError().isEmpty()) {
  76.181 -                w.append("    t.printStackTrace();");
  76.182 -            } else {
  76.183 -                if (!findOnError(me, te, ol.onError(), isStatic)) {
  76.184 -                    return false;
  76.185 -                }
  76.186 -                if (isStatic) {
  76.187 -                    w.append("    ").append(te.getSimpleName()).append(".");
  76.188 -                } else {
  76.189 -                    w.append("    $i.");
  76.190 -                }
  76.191 -                w.append(ol.onError()).append("(t");
  76.192 -                for (int i = 1; i < params.size(); i++) {
  76.193 -                    final VariableElement p = params.get(i);
  76.194 -                    w.append(", ").append(p.getSimpleName());
  76.195 -                }
  76.196 -                w.append(");\n");
  76.197 -            }
  76.198 -            w.append("  }\n");
  76.199 -            w.append("  @Override protected void onLocation(net.java.html.geo.Position p) throws Throwable {\n");
  76.200 -            if (isStatic) {
  76.201 -                w.append("    ").append(te.getSimpleName()).append(".");
  76.202 -            } else {
  76.203 -                w.append("    $i.");
  76.204 -            }
  76.205 -            w.append(me.getSimpleName()).append("(p");
  76.206 -            for (int i = 1; i < params.size(); i++) {
  76.207 -                final VariableElement p = params.get(i);
  76.208 -                w.append(", ").append(p.getSimpleName());
  76.209 -            }
  76.210 -            w.append(");\n");
  76.211 -            w.append("  }\n");
  76.212 -            w.append("}\n");
  76.213 -            w.close();
  76.214 -        } catch (IOException ex) {
  76.215 -            Logger.getLogger(GeoProcessor.class.getName()).log(Level.SEVERE, null, ex);
  76.216 -            error("Can't write handler class: " + ex.getMessage(), e);
  76.217 -            return false;
  76.218 -        }
  76.219 -        
  76.220 -        return true;
  76.221 -    }
  76.222 -
  76.223 -    private boolean findOnError(ExecutableElement errElem, TypeElement te, String name, boolean onlyStatic) {
  76.224 -        String err = null;
  76.225 -        METHODS: for (Element e : te.getEnclosedElements()) {
  76.226 -            if (e.getKind() != ElementKind.METHOD) {
  76.227 -                continue;
  76.228 -            }
  76.229 -            if (!e.getSimpleName().contentEquals(name)) {
  76.230 -                continue;
  76.231 -            }
  76.232 -            if (onlyStatic && !e.getModifiers().contains(Modifier.STATIC)) {
  76.233 -                errElem = (ExecutableElement) e;
  76.234 -                err = "Would have to be static";
  76.235 -                continue;
  76.236 -            }
  76.237 -            ExecutableElement ee = (ExecutableElement) e;
  76.238 -            TypeMirror excType = processingEnv.getElementUtils().getTypeElement(Exception.class.getName()).asType();
  76.239 -            final List<? extends VariableElement> params = ee.getParameters(); 
  76.240 -            if (params.size() < 1 || 
  76.241 -                !processingEnv.getTypeUtils().isAssignable(excType, ee.getParameters().get(0).asType())
  76.242 -            ) {
  76.243 -                errElem = (ExecutableElement) e;
  76.244 -                err = "Error method first argument needs to be Exception";
  76.245 -                continue;
  76.246 -            }
  76.247 -            final List<? extends Element> origParams = errElem.getParameters();
  76.248 -            if (params.size() != origParams.size()) {
  76.249 -                errElem = (ExecutableElement) e;
  76.250 -                err = "Error method must have the same parameters as @OnLocation one";
  76.251 -                continue;
  76.252 -            }
  76.253 -            for (int i = 1; i < origParams.size(); i++) {
  76.254 -                final TypeMirror t1 = params.get(i).asType();
  76.255 -                final TypeMirror t2 = origParams.get(i).asType();
  76.256 -                if (!processingEnv.getTypeUtils().isSameType(t1, t2)) {
  76.257 -                    errElem = (ExecutableElement) e;
  76.258 -                    err = "Error method must have the same parameters as @OnLocation one";
  76.259 -                    continue METHODS;
  76.260 -                }
  76.261 -            }
  76.262 -            return true;
  76.263 -        }
  76.264 -        if (err == null) {
  76.265 -            err = "Cannot find " + name + "(Exception) method in this class";
  76.266 -        }
  76.267 -        error(err, errElem);
  76.268 -        return false;
  76.269 -    }
  76.270 -}
    77.1 --- a/geo/src/main/java/org/apidesign/html/geo/impl/JsG.java	Mon Dec 16 17:16:02 2013 +0100
    77.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    77.3 @@ -1,85 +0,0 @@
    77.4 -/**
    77.5 - * HTML via Java(tm) Language Bindings
    77.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    77.7 - *
    77.8 - * This program is free software: you can redistribute it and/or modify
    77.9 - * it under the terms of the GNU General Public License as published by
   77.10 - * the Free Software Foundation, version 2 of the License.
   77.11 - *
   77.12 - * This program is distributed in the hope that it will be useful,
   77.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   77.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   77.15 - * GNU General Public License for more details. apidesign.org
   77.16 - * designates this particular file as subject to the
   77.17 - * "Classpath" exception as provided by apidesign.org
   77.18 - * in the License file that accompanied this code.
   77.19 - *
   77.20 - * You should have received a copy of the GNU General Public License
   77.21 - * along with this program. Look for COPYING file in the top folder.
   77.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   77.23 - */
   77.24 -package org.apidesign.html.geo.impl;
   77.25 -
   77.26 -import net.java.html.js.JavaScriptBody;
   77.27 -
   77.28 -/** Implementation class to deal with browser's <code>navigator.geolocation</code> 
   77.29 - * object.
   77.30 - *
   77.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   77.32 - */
   77.33 -public abstract class JsG {
   77.34 -    protected JsG() {
   77.35 -        if (!getClass().getName().equals("net.java.html.geo.Position$Handle$JsH")) {
   77.36 -            throw new IllegalStateException();
   77.37 -        }
   77.38 -    }
   77.39 -    
   77.40 -    public abstract void onLocation(Object position);
   77.41 -    public abstract void onError(Object error);
   77.42 -    
   77.43 -    @JavaScriptBody(args = {}, body = "return !!navigator.geolocation;")
   77.44 -    public static boolean hasGeolocation() {
   77.45 -        return false;
   77.46 -    }
   77.47 -
   77.48 -    @JavaScriptBody(
   77.49 -        args = { "onlyOnce", "enableHighAccuracy", "timeout", "maximumAge" }, 
   77.50 -        javacall = true, 
   77.51 -        body = 
   77.52 -        "var self = this;\n" +
   77.53 -        "var ok = function (position) {\n" +
   77.54 -        "  self.@org.apidesign.html.geo.impl.JsG::onLocation(Ljava/lang/Object;)(position);\n" +
   77.55 -        "};\n" +
   77.56 -        "var fail = function (error) {\n" +
   77.57 -        "  self.@org.apidesign.html.geo.impl.JsG::onError(Ljava/lang/Object;)(error);\n" +
   77.58 -        "};\n" +
   77.59 -        "var options = {};\n" +
   77.60 -        "options.enableHighAccuracy = enableHighAccuracy;\n" +
   77.61 -        "if (timeout >= 0) options.timeout = timeout;\n" +
   77.62 -        "if (maximumAge >= 0) options.maximumAge = maximumAge;\n" +
   77.63 -        "if (onlyOnce) {\n" +
   77.64 -        "  navigator.geolocation.getCurrentPosition(ok, fail);\n" +
   77.65 -        "  return 0;\n" +
   77.66 -        "} else {\n" +
   77.67 -        "  return navigator.geolocation.watchPosition(ok, fail);\n" +
   77.68 -        "}\n"
   77.69 -    )
   77.70 -    protected long start(
   77.71 -        boolean onlyOnce, 
   77.72 -        boolean enableHighAccuracy,
   77.73 -        long timeout,
   77.74 -        long maximumAge
   77.75 -    ) {
   77.76 -        return -1;
   77.77 -    }
   77.78 -    
   77.79 -    @JavaScriptBody(args = { "watch" }, body = "navigator.geolocation.clearWatch(watch);")
   77.80 -    protected void stop(long watch) {
   77.81 -    }
   77.82 -
   77.83 -    @JavaScriptBody(args = { "self", "property" }, body = "return self[property];")
   77.84 -    public static Object get(Object self, String property) {
   77.85 -        return null;
   77.86 -    }
   77.87 -
   77.88 -}
    78.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    78.2 +++ b/geo/src/main/java/org/netbeans/html/geo/impl/GeoProcessor.java	Mon Dec 16 17:16:40 2013 +0100
    78.3 @@ -0,0 +1,289 @@
    78.4 +/**
    78.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    78.6 + *
    78.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    78.8 + *
    78.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   78.10 + * Other names may be trademarks of their respective owners.
   78.11 + *
   78.12 + * The contents of this file are subject to the terms of either the GNU
   78.13 + * General Public License Version 2 only ("GPL") or the Common
   78.14 + * Development and Distribution License("CDDL") (collectively, the
   78.15 + * "License"). You may not use this file except in compliance with the
   78.16 + * License. You can obtain a copy of the License at
   78.17 + * http://www.netbeans.org/cddl-gplv2.html
   78.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   78.19 + * specific language governing permissions and limitations under the
   78.20 + * License.  When distributing the software, include this License Header
   78.21 + * Notice in each file and include the License file at
   78.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   78.23 + * particular file as subject to the "Classpath" exception as provided
   78.24 + * by Oracle in the GPL Version 2 section of the License file that
   78.25 + * accompanied this code. If applicable, add the following below the
   78.26 + * License Header, with the fields enclosed by brackets [] replaced by
   78.27 + * your own identifying information:
   78.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   78.29 + *
   78.30 + * Contributor(s):
   78.31 + *
   78.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   78.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   78.34 + *
   78.35 + * If you wish your version of this file to be governed by only the CDDL
   78.36 + * or only the GPL Version 2, indicate your decision by adding
   78.37 + * "[Contributor] elects to include this software in this distribution
   78.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   78.39 + * single choice of license, a recipient has the option to distribute
   78.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   78.41 + * to extend the choice of license to its licensees as provided above.
   78.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   78.43 + * Version 2 license, then the option applies only if the new code is
   78.44 + * made subject to such option by the copyright holder.
   78.45 + */
   78.46 +package org.netbeans.html.geo.impl;
   78.47 +
   78.48 +import java.io.IOException;
   78.49 +import java.io.Writer;
   78.50 +import java.util.List;
   78.51 +import java.util.Locale;
   78.52 +import java.util.Set;
   78.53 +import java.util.logging.Level;
   78.54 +import java.util.logging.Logger;
   78.55 +import javax.annotation.processing.AbstractProcessor;
   78.56 +import javax.annotation.processing.Processor;
   78.57 +import javax.annotation.processing.RoundEnvironment;
   78.58 +import javax.annotation.processing.SupportedAnnotationTypes;
   78.59 +import javax.annotation.processing.SupportedSourceVersion;
   78.60 +import javax.lang.model.SourceVersion;
   78.61 +import javax.lang.model.element.Element;
   78.62 +import javax.lang.model.element.ElementKind;
   78.63 +import javax.lang.model.element.ExecutableElement;
   78.64 +import javax.lang.model.element.Modifier;
   78.65 +import javax.lang.model.element.PackageElement;
   78.66 +import javax.lang.model.element.TypeElement;
   78.67 +import javax.lang.model.element.VariableElement;
   78.68 +import javax.lang.model.type.TypeMirror;
   78.69 +import javax.tools.Diagnostic;
   78.70 +import javax.tools.JavaFileObject;
   78.71 +import net.java.html.geo.OnLocation;
   78.72 +import net.java.html.geo.Position;
   78.73 +import org.openide.util.lookup.ServiceProvider;
   78.74 +
   78.75 +/** Annotation processor to generate callbacks from {@link GeoHandle} class.
   78.76 + *
   78.77 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   78.78 + */
   78.79 +@ServiceProvider(service=Processor.class)
   78.80 +@SupportedSourceVersion(SourceVersion.RELEASE_6)
   78.81 +@SupportedAnnotationTypes({
   78.82 +    "net.java.html.geo.OnLocation"
   78.83 +})
   78.84 +public final class GeoProcessor extends AbstractProcessor {
   78.85 +    private static final Logger LOG = Logger.getLogger(GeoProcessor.class.getName());
   78.86 +    @Override
   78.87 +    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
   78.88 +        boolean ok = true;
   78.89 +        for (Element e : roundEnv.getElementsAnnotatedWith(OnLocation.class)) {
   78.90 +            if (!processLocation(e)) {
   78.91 +                ok = false;
   78.92 +            }
   78.93 +        }
   78.94 +        return ok;
   78.95 +    }
   78.96 +
   78.97 +    private void error(String msg, Element e) {
   78.98 +        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e);
   78.99 +    }
  78.100 +    
  78.101 +    private boolean processLocation(Element e) {
  78.102 +        if (e.getKind() != ElementKind.METHOD) {
  78.103 +            return false;
  78.104 +        }
  78.105 +        ExecutableElement me = (ExecutableElement) e;
  78.106 +        OnLocation ol = e.getAnnotation(OnLocation.class);
  78.107 +        if (ol == null) {
  78.108 +            return true;
  78.109 +        }
  78.110 +        if (me.getModifiers().contains(Modifier.PRIVATE)) {
  78.111 +            error("Method annotated by @OnLocation cannot be private", e);
  78.112 +            return false;
  78.113 +        }
  78.114 +        TypeMirror positionClass = processingEnv.getElementUtils().getTypeElement(Position.class.getName()).asType();
  78.115 +        final List<? extends VariableElement> params = me.getParameters();
  78.116 +        if (params.size() < 1 || !params.get(0).asType().equals(positionClass)) {
  78.117 +            error("Method annotated by @OnLocation first argument must be net.java.html.geo.Position!", e);
  78.118 +            return false;
  78.119 +        }
  78.120 +        String className = ol.className();
  78.121 +        if (className.isEmpty()) {
  78.122 +            String n = e.getSimpleName().toString();
  78.123 +            if (n.isEmpty()) {
  78.124 +                error("Empty method name", e);
  78.125 +                return false;
  78.126 +            }
  78.127 +            final String firstLetter = n.substring(0, 1).toUpperCase(Locale.ENGLISH);
  78.128 +            className = firstLetter + n.substring(1) + "Handle";
  78.129 +        }
  78.130 +        TypeElement te = (TypeElement)e.getEnclosingElement();
  78.131 +        PackageElement pe = (PackageElement) te.getEnclosingElement();
  78.132 +        final String pkg = pe.getQualifiedName().toString();
  78.133 +        final String fqn = pkg + "." + className;
  78.134 +        final boolean isStatic = me.getModifiers().contains(Modifier.STATIC);
  78.135 +        String sep;
  78.136 +        try {
  78.137 +            JavaFileObject fo = processingEnv.getFiler().createSourceFile(fqn, e);
  78.138 +            Writer w = fo.openWriter();
  78.139 +            w.append("package ").append(pkg).append(";\n");
  78.140 +            w.append("class ").append(className).append(" extends net.java.html.geo.Position.Handle {\n");
  78.141 +            if (!isStatic) {
  78.142 +                w.append("  private final ").append(te.getSimpleName()).append(" $i;\n");
  78.143 +            }
  78.144 +            for (int i = 1; i < params.size(); i++) {
  78.145 +                final VariableElement p = params.get(i);
  78.146 +                w.append("  private final ").append(p.asType().toString()).append(" ").append(p.getSimpleName()).append(";\n");
  78.147 +            }
  78.148 +            w.append("  private ").append(className).append("(boolean oneTime");
  78.149 +            w.append(", ").append(te.getSimpleName()).append(" i");
  78.150 +            for (int i = 1; i < params.size(); i++) {
  78.151 +                final VariableElement p = params.get(i);
  78.152 +                w.append(", ").append(p.asType().toString()).append(" ").append(p.getSimpleName());
  78.153 +            }
  78.154 +            w.append(") {\n    super(oneTime);\n");
  78.155 +            if (!isStatic) {
  78.156 +                w.append("    this.$i = i;\n");
  78.157 +            }
  78.158 +            for (int i = 1; i < params.size(); i++) {
  78.159 +                final VariableElement p = params.get(i);
  78.160 +                w.append("  this.").append(p.getSimpleName()).append(" = ").append(p.getSimpleName()).append(";\n");
  78.161 +            }
  78.162 +            w.append("}\n");
  78.163 +            w.append("  static net.java.html.geo.Position.Handle createQuery(");
  78.164 +            String inst;
  78.165 +            if (!isStatic) {
  78.166 +                w.append(te.getSimpleName()).append(" instance");
  78.167 +                inst = "instance";
  78.168 +                sep = ", ";
  78.169 +            } else {
  78.170 +                inst = "null";
  78.171 +                sep = "";
  78.172 +            }
  78.173 +            for (int i = 1; i < params.size(); i++) {
  78.174 +                final VariableElement p = params.get(i);
  78.175 +                w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName());
  78.176 +                sep = ", ";
  78.177 +            }
  78.178 +            w.append(") { return new ").append(className).append("(true, ").append(inst);
  78.179 +            for (int i = 1; i < params.size(); i++) {
  78.180 +                final VariableElement p = params.get(i);
  78.181 +                w.append(", ").append(p.getSimpleName());
  78.182 +            }
  78.183 +            w.append("); }\n");
  78.184 +            w.append("  static net.java.html.geo.Position.Handle createWatch(");
  78.185 +            if (!isStatic) {
  78.186 +                w.append(te.getSimpleName()).append(" instance");
  78.187 +                sep = ", ";
  78.188 +            } else {
  78.189 +                sep = "";
  78.190 +            }
  78.191 +            for (int i = 1; i < params.size(); i++) {
  78.192 +                final VariableElement p = params.get(i);
  78.193 +                w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName());
  78.194 +            }
  78.195 +            w.append(") { return new ").append(className).append("(false, ").append(inst);
  78.196 +            for (int i = 1; i < params.size(); i++) {
  78.197 +                final VariableElement p = params.get(i);
  78.198 +                w.append(", ").append(p.getSimpleName());
  78.199 +            }
  78.200 +            w.append("); }\n");
  78.201 +            w.append("  @Override protected void onError(Exception t) throws Throwable {\n");
  78.202 +            if (ol.onError().isEmpty()) {
  78.203 +                w.append("    t.printStackTrace();");
  78.204 +            } else {
  78.205 +                if (!findOnError(me, te, ol.onError(), isStatic)) {
  78.206 +                    return false;
  78.207 +                }
  78.208 +                if (isStatic) {
  78.209 +                    w.append("    ").append(te.getSimpleName()).append(".");
  78.210 +                } else {
  78.211 +                    w.append("    $i.");
  78.212 +                }
  78.213 +                w.append(ol.onError()).append("(t");
  78.214 +                for (int i = 1; i < params.size(); i++) {
  78.215 +                    final VariableElement p = params.get(i);
  78.216 +                    w.append(", ").append(p.getSimpleName());
  78.217 +                }
  78.218 +                w.append(");\n");
  78.219 +            }
  78.220 +            w.append("  }\n");
  78.221 +            w.append("  @Override protected void onLocation(net.java.html.geo.Position p) throws Throwable {\n");
  78.222 +            if (isStatic) {
  78.223 +                w.append("    ").append(te.getSimpleName()).append(".");
  78.224 +            } else {
  78.225 +                w.append("    $i.");
  78.226 +            }
  78.227 +            w.append(me.getSimpleName()).append("(p");
  78.228 +            for (int i = 1; i < params.size(); i++) {
  78.229 +                final VariableElement p = params.get(i);
  78.230 +                w.append(", ").append(p.getSimpleName());
  78.231 +            }
  78.232 +            w.append(");\n");
  78.233 +            w.append("  }\n");
  78.234 +            w.append("}\n");
  78.235 +            w.close();
  78.236 +        } catch (IOException ex) {
  78.237 +            Logger.getLogger(GeoProcessor.class.getName()).log(Level.SEVERE, null, ex);
  78.238 +            error("Can't write handler class: " + ex.getMessage(), e);
  78.239 +            return false;
  78.240 +        }
  78.241 +        
  78.242 +        return true;
  78.243 +    }
  78.244 +
  78.245 +    private boolean findOnError(ExecutableElement errElem, TypeElement te, String name, boolean onlyStatic) {
  78.246 +        String err = null;
  78.247 +        METHODS: for (Element e : te.getEnclosedElements()) {
  78.248 +            if (e.getKind() != ElementKind.METHOD) {
  78.249 +                continue;
  78.250 +            }
  78.251 +            if (!e.getSimpleName().contentEquals(name)) {
  78.252 +                continue;
  78.253 +            }
  78.254 +            if (onlyStatic && !e.getModifiers().contains(Modifier.STATIC)) {
  78.255 +                errElem = (ExecutableElement) e;
  78.256 +                err = "Would have to be static";
  78.257 +                continue;
  78.258 +            }
  78.259 +            ExecutableElement ee = (ExecutableElement) e;
  78.260 +            TypeMirror excType = processingEnv.getElementUtils().getTypeElement(Exception.class.getName()).asType();
  78.261 +            final List<? extends VariableElement> params = ee.getParameters(); 
  78.262 +            if (params.size() < 1 || 
  78.263 +                !processingEnv.getTypeUtils().isAssignable(excType, ee.getParameters().get(0).asType())
  78.264 +            ) {
  78.265 +                errElem = (ExecutableElement) e;
  78.266 +                err = "Error method first argument needs to be Exception";
  78.267 +                continue;
  78.268 +            }
  78.269 +            final List<? extends Element> origParams = errElem.getParameters();
  78.270 +            if (params.size() != origParams.size()) {
  78.271 +                errElem = (ExecutableElement) e;
  78.272 +                err = "Error method must have the same parameters as @OnLocation one";
  78.273 +                continue;
  78.274 +            }
  78.275 +            for (int i = 1; i < origParams.size(); i++) {
  78.276 +                final TypeMirror t1 = params.get(i).asType();
  78.277 +                final TypeMirror t2 = origParams.get(i).asType();
  78.278 +                if (!processingEnv.getTypeUtils().isSameType(t1, t2)) {
  78.279 +                    errElem = (ExecutableElement) e;
  78.280 +                    err = "Error method must have the same parameters as @OnLocation one";
  78.281 +                    continue METHODS;
  78.282 +                }
  78.283 +            }
  78.284 +            return true;
  78.285 +        }
  78.286 +        if (err == null) {
  78.287 +            err = "Cannot find " + name + "(Exception) method in this class";
  78.288 +        }
  78.289 +        error(err, errElem);
  78.290 +        return false;
  78.291 +    }
  78.292 +}
    79.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    79.2 +++ b/geo/src/main/java/org/netbeans/html/geo/impl/JsG.java	Mon Dec 16 17:16:40 2013 +0100
    79.3 @@ -0,0 +1,107 @@
    79.4 +/**
    79.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    79.6 + *
    79.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    79.8 + *
    79.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   79.10 + * Other names may be trademarks of their respective owners.
   79.11 + *
   79.12 + * The contents of this file are subject to the terms of either the GNU
   79.13 + * General Public License Version 2 only ("GPL") or the Common
   79.14 + * Development and Distribution License("CDDL") (collectively, the
   79.15 + * "License"). You may not use this file except in compliance with the
   79.16 + * License. You can obtain a copy of the License at
   79.17 + * http://www.netbeans.org/cddl-gplv2.html
   79.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   79.19 + * specific language governing permissions and limitations under the
   79.20 + * License.  When distributing the software, include this License Header
   79.21 + * Notice in each file and include the License file at
   79.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   79.23 + * particular file as subject to the "Classpath" exception as provided
   79.24 + * by Oracle in the GPL Version 2 section of the License file that
   79.25 + * accompanied this code. If applicable, add the following below the
   79.26 + * License Header, with the fields enclosed by brackets [] replaced by
   79.27 + * your own identifying information:
   79.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   79.29 + *
   79.30 + * Contributor(s):
   79.31 + *
   79.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   79.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   79.34 + *
   79.35 + * If you wish your version of this file to be governed by only the CDDL
   79.36 + * or only the GPL Version 2, indicate your decision by adding
   79.37 + * "[Contributor] elects to include this software in this distribution
   79.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   79.39 + * single choice of license, a recipient has the option to distribute
   79.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   79.41 + * to extend the choice of license to its licensees as provided above.
   79.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   79.43 + * Version 2 license, then the option applies only if the new code is
   79.44 + * made subject to such option by the copyright holder.
   79.45 + */
   79.46 +package org.netbeans.html.geo.impl;
   79.47 +
   79.48 +import net.java.html.js.JavaScriptBody;
   79.49 +
   79.50 +/** Implementation class to deal with browser's <code>navigator.geolocation</code> 
   79.51 + * object.
   79.52 + *
   79.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   79.54 + */
   79.55 +public abstract class JsG {
   79.56 +    protected JsG() {
   79.57 +        if (!getClass().getName().equals("net.java.html.geo.Position$Handle$JsH")) {
   79.58 +            throw new IllegalStateException();
   79.59 +        }
   79.60 +    }
   79.61 +    
   79.62 +    public abstract void onLocation(Object position);
   79.63 +    public abstract void onError(Object error);
   79.64 +    
   79.65 +    @JavaScriptBody(args = {}, body = "return !!navigator.geolocation;")
   79.66 +    public static boolean hasGeolocation() {
   79.67 +        return false;
   79.68 +    }
   79.69 +
   79.70 +    @JavaScriptBody(
   79.71 +        args = { "onlyOnce", "enableHighAccuracy", "timeout", "maximumAge" }, 
   79.72 +        javacall = true, 
   79.73 +        body = 
   79.74 +        "var self = this;\n" +
   79.75 +        "var ok = function (position) {\n" +
   79.76 +        "  self.@org.netbeans.html.geo.impl.JsG::onLocation(Ljava/lang/Object;)(position);\n" +
   79.77 +        "};\n" +
   79.78 +        "var fail = function (error) {\n" +
   79.79 +        "  self.@org.netbeans.html.geo.impl.JsG::onError(Ljava/lang/Object;)(error);\n" +
   79.80 +        "};\n" +
   79.81 +        "var options = {};\n" +
   79.82 +        "options.enableHighAccuracy = enableHighAccuracy;\n" +
   79.83 +        "if (timeout >= 0) options.timeout = timeout;\n" +
   79.84 +        "if (maximumAge >= 0) options.maximumAge = maximumAge;\n" +
   79.85 +        "if (onlyOnce) {\n" +
   79.86 +        "  navigator.geolocation.getCurrentPosition(ok, fail);\n" +
   79.87 +        "  return 0;\n" +
   79.88 +        "} else {\n" +
   79.89 +        "  return navigator.geolocation.watchPosition(ok, fail);\n" +
   79.90 +        "}\n"
   79.91 +    )
   79.92 +    protected long start(
   79.93 +        boolean onlyOnce, 
   79.94 +        boolean enableHighAccuracy,
   79.95 +        long timeout,
   79.96 +        long maximumAge
   79.97 +    ) {
   79.98 +        return -1;
   79.99 +    }
  79.100 +    
  79.101 +    @JavaScriptBody(args = { "watch" }, body = "navigator.geolocation.clearWatch(watch);")
  79.102 +    protected void stop(long watch) {
  79.103 +    }
  79.104 +
  79.105 +    @JavaScriptBody(args = { "self", "property" }, body = "return self[property];")
  79.106 +    public static Object get(Object self, String property) {
  79.107 +        return null;
  79.108 +    }
  79.109 +
  79.110 +}
    80.1 --- a/geo/src/test/java/net/java/html/geo/OnLocationTest.java	Mon Dec 16 17:16:02 2013 +0100
    80.2 +++ b/geo/src/test/java/net/java/html/geo/OnLocationTest.java	Mon Dec 16 17:16:40 2013 +0100
    80.3 @@ -1,22 +1,44 @@
    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 1997-2010 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  
    81.1 --- a/geo/src/test/java/org/apidesign/html/geo/impl/Compile.java	Mon Dec 16 17:16:02 2013 +0100
    81.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    81.3 @@ -1,264 +0,0 @@
    81.4 -/**
    81.5 - * HTML via Java(tm) Language Bindings
    81.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    81.7 - *
    81.8 - * This program is free software: you can redistribute it and/or modify
    81.9 - * it under the terms of the GNU General Public License as published by
   81.10 - * the Free Software Foundation, version 2 of the License.
   81.11 - *
   81.12 - * This program is distributed in the hope that it will be useful,
   81.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   81.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   81.15 - * GNU General Public License for more details. apidesign.org
   81.16 - * designates this particular file as subject to the
   81.17 - * "Classpath" exception as provided by apidesign.org
   81.18 - * in the License file that accompanied this code.
   81.19 - *
   81.20 - * You should have received a copy of the GNU General Public License
   81.21 - * along with this program. Look for COPYING file in the top folder.
   81.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   81.23 - */
   81.24 -package org.apidesign.html.geo.impl;
   81.25 -
   81.26 -import java.io.ByteArrayInputStream;
   81.27 -import java.io.ByteArrayOutputStream;
   81.28 -import java.io.IOException;
   81.29 -import java.io.InputStream;
   81.30 -import java.io.OutputStream;
   81.31 -import java.net.URI;
   81.32 -import java.net.URISyntaxException;
   81.33 -import java.util.ArrayList;
   81.34 -import java.util.Arrays;
   81.35 -import java.util.HashMap;
   81.36 -import java.util.List;
   81.37 -import java.util.Locale;
   81.38 -import java.util.Map;
   81.39 -import java.util.regex.Matcher;
   81.40 -import java.util.regex.Pattern;
   81.41 -import javax.tools.Diagnostic;
   81.42 -import javax.tools.DiagnosticListener;
   81.43 -import javax.tools.FileObject;
   81.44 -import javax.tools.ForwardingJavaFileManager;
   81.45 -import javax.tools.JavaFileManager;
   81.46 -import javax.tools.JavaFileObject;
   81.47 -import javax.tools.JavaFileObject.Kind;
   81.48 -import javax.tools.SimpleJavaFileObject;
   81.49 -import javax.tools.StandardJavaFileManager;
   81.50 -import javax.tools.StandardLocation;
   81.51 -import javax.tools.ToolProvider;
   81.52 -import static org.testng.Assert.*;
   81.53 -
   81.54 -/**
   81.55 - *
   81.56 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   81.57 - */
   81.58 -final class Compile implements DiagnosticListener<JavaFileObject> {
   81.59 -    private final List<Diagnostic<? extends JavaFileObject>> errors = 
   81.60 -            new ArrayList<Diagnostic<? extends JavaFileObject>>();
   81.61 -    private final Map<String, byte[]> classes;
   81.62 -    private final String pkg;
   81.63 -    private final String cls;
   81.64 -    private final String html;
   81.65 -    private final String sourceLevel;
   81.66 -
   81.67 -    private Compile(String html, String code, String sl) throws IOException {
   81.68 -        this.pkg = findPkg(code);
   81.69 -        this.cls = findCls(code);
   81.70 -        this.html = html;
   81.71 -        this.sourceLevel = sl;
   81.72 -        classes = compile(html, code);
   81.73 -    }
   81.74 -
   81.75 -    /** Performs compilation of given HTML page and associated Java code
   81.76 -     */
   81.77 -    public static Compile create(String html, String code) throws IOException {
   81.78 -        return create(html, code, "1.7");
   81.79 -    }
   81.80 -    static Compile create(String html, String code, String sourceLevel) throws IOException {
   81.81 -        return new Compile(html, code, sourceLevel);
   81.82 -    }
   81.83 -    
   81.84 -    /** Checks for given class among compiled resources */
   81.85 -    public byte[] get(String res) {
   81.86 -        return classes.get(res);
   81.87 -    }
   81.88 -    
   81.89 -    /** Obtains errors created during compilation.
   81.90 -     */
   81.91 -    public List<Diagnostic<? extends JavaFileObject>> getErrors() {
   81.92 -        List<Diagnostic<? extends JavaFileObject>> err;
   81.93 -        err = new ArrayList<Diagnostic<? extends JavaFileObject>>();
   81.94 -        for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
   81.95 -            if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
   81.96 -                err.add(diagnostic);
   81.97 -            }
   81.98 -        }
   81.99 -        return err;
  81.100 -    }
  81.101 -    
  81.102 -    private Map<String, byte[]> compile(final String html, final String code) throws IOException {
  81.103 -        StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
  81.104 -
  81.105 -        final Map<String, ByteArrayOutputStream> class2BAOS;
  81.106 -        class2BAOS = new HashMap<String, ByteArrayOutputStream>();
  81.107 -
  81.108 -        JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
  81.109 -            @Override
  81.110 -            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  81.111 -                return code;
  81.112 -            }
  81.113 -        };
  81.114 -        final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
  81.115 -            @Override
  81.116 -            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  81.117 -                return html;
  81.118 -            }
  81.119 -
  81.120 -            @Override
  81.121 -            public InputStream openInputStream() throws IOException {
  81.122 -                return new ByteArrayInputStream(html.getBytes());
  81.123 -            }
  81.124 -        };
  81.125 -        
  81.126 -        final URI scratch;
  81.127 -        try {
  81.128 -            scratch = new URI("mem://mem3");
  81.129 -        } catch (URISyntaxException ex) {
  81.130 -            throw new IOException(ex);
  81.131 -        }
  81.132 -        
  81.133 -        JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
  81.134 -            @Override
  81.135 -            public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
  81.136 -                if (kind  == Kind.CLASS) {
  81.137 -                    final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
  81.138 -
  81.139 -                    class2BAOS.put(className.replace('.', '/') + ".class", buffer);
  81.140 -                    return new SimpleJavaFileObject(sibling.toUri(), kind) {
  81.141 -                        @Override
  81.142 -                        public OutputStream openOutputStream() throws IOException {
  81.143 -                            return buffer;
  81.144 -                        }
  81.145 -                    };
  81.146 -                }
  81.147 -                
  81.148 -                if (kind == Kind.SOURCE) {
  81.149 -                    final String n = className.replace('.', '/') + ".java";
  81.150 -                    final URI un;
  81.151 -                    try {
  81.152 -                        un = new URI("mem://" + n);
  81.153 -                    } catch (URISyntaxException ex) {
  81.154 -                        throw new IOException(ex);
  81.155 -                    }
  81.156 -                    return new VirtFO(un/*sibling.toUri()*/, kind, n);
  81.157 -                }
  81.158 -                
  81.159 -                throw new IllegalStateException();
  81.160 -            }
  81.161 -
  81.162 -            @Override
  81.163 -            public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
  81.164 -                if (location == StandardLocation.SOURCE_PATH) {
  81.165 -                    if (packageName.equals(pkg)) {
  81.166 -                        return htmlFile;
  81.167 -                    }
  81.168 -                }
  81.169 -                
  81.170 -                return null;
  81.171 -            }
  81.172 -
  81.173 -            @Override
  81.174 -            public boolean isSameFile(FileObject a, FileObject b) {
  81.175 -                if (a instanceof VirtFO && b instanceof VirtFO) {
  81.176 -                    return ((VirtFO)a).getName().equals(((VirtFO)b).getName());
  81.177 -                }
  81.178 -                
  81.179 -                return super.isSameFile(a, b);
  81.180 -            }
  81.181 -
  81.182 -            class VirtFO extends SimpleJavaFileObject {
  81.183 -
  81.184 -                private final String n;
  81.185 -
  81.186 -                public VirtFO(URI uri, Kind kind, String n) {
  81.187 -                    super(uri, kind);
  81.188 -                    this.n = n;
  81.189 -                }
  81.190 -                private final ByteArrayOutputStream data = new ByteArrayOutputStream();
  81.191 -
  81.192 -                @Override
  81.193 -                public OutputStream openOutputStream() throws IOException {
  81.194 -                    return data;
  81.195 -                }
  81.196 -
  81.197 -                @Override
  81.198 -                public String getName() {
  81.199 -                    return n;
  81.200 -                }
  81.201 -
  81.202 -                @Override
  81.203 -                public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  81.204 -                    data.close();
  81.205 -                    return new String(data.toByteArray());
  81.206 -                }
  81.207 -            }
  81.208 -        };
  81.209 -
  81.210 -        ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", sourceLevel, "-target", "1.7"), null, Arrays.asList(file)).call();
  81.211 -
  81.212 -        Map<String, byte[]> result = new HashMap<String, byte[]>();
  81.213 -
  81.214 -        for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
  81.215 -            result.put(e.getKey(), e.getValue().toByteArray());
  81.216 -        }
  81.217 -
  81.218 -        return result;
  81.219 -    }
  81.220 -
  81.221 -
  81.222 -    @Override
  81.223 -    public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
  81.224 -        errors.add(diagnostic);
  81.225 -    }
  81.226 -    private static String findPkg(String java) throws IOException {
  81.227 -        Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
  81.228 -        Matcher m = p.matcher(java);
  81.229 -        if (!m.find()) {
  81.230 -            throw new IOException("Can't find package declaration in the java file");
  81.231 -        }
  81.232 -        String pkg = m.group(1);
  81.233 -        return pkg;
  81.234 -    }
  81.235 -    private static String findCls(String java) throws IOException {
  81.236 -        Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
  81.237 -        Matcher m = p.matcher(java);
  81.238 -        if (!m.find()) {
  81.239 -            throw new IOException("Can't find package declaration in the java file");
  81.240 -        }
  81.241 -        String cls = m.group(1);
  81.242 -        return cls;
  81.243 -    }
  81.244 -
  81.245 -    String getHtml() {
  81.246 -        String fqn = "'" + pkg + '.' + cls + "'";
  81.247 -        return html.replace("'${fqn}'", fqn);
  81.248 -    }
  81.249 -
  81.250 -    void assertErrors() {
  81.251 -        assertFalse(getErrors().isEmpty(), "There are supposed to be some errors");
  81.252 -    }
  81.253 -
  81.254 -    void assertError(String expMsg) {
  81.255 -        StringBuilder sb = new StringBuilder();
  81.256 -        sb.append("Can't find ").append(expMsg).append(" among:");
  81.257 -        for (Diagnostic<? extends JavaFileObject> e : errors) {
  81.258 -            String msg = e.getMessage(Locale.US);
  81.259 -            if (msg.contains(expMsg)) {
  81.260 -                return;
  81.261 -            }
  81.262 -            sb.append("\n");
  81.263 -            sb.append(msg);
  81.264 -        }
  81.265 -        fail(sb.toString());
  81.266 -    }
  81.267 -}
    82.1 --- a/geo/src/test/java/org/apidesign/html/geo/impl/GeoProcessorTest.java	Mon Dec 16 17:16:02 2013 +0100
    82.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    82.3 @@ -1,92 +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 org.testng.annotations.Test;
   82.28 -
   82.29 -/** Test whether the annotation processor detects errors correctly.
   82.30 - *
   82.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   82.32 - */
   82.33 -public class GeoProcessorTest {
   82.34 -    
   82.35 -    public GeoProcessorTest() {
   82.36 -    }
   82.37 -
   82.38 -    @Test public void onLocationMethodHasToTakePositionParameter() throws IOException {
   82.39 -        Compile res = Compile.create("", "package x;\n"
   82.40 -            + "class UseOnLocation {\n"
   82.41 -            + "  @net.java.html.geo.OnLocation\n"
   82.42 -            + "  public static void cantCallMe() {}\n"
   82.43 -            + "}\n"
   82.44 -        );
   82.45 -        res.assertErrors();
   82.46 -        res.assertError("first argument must be net.java.html.geo.Position");
   82.47 -    }
   82.48 -    
   82.49 -    @Test public void onLocationMethodCannotBePrivate() throws IOException {
   82.50 -        Compile res = Compile.create("", "package x;\n"
   82.51 -            + "class UseOnLocation {\n"
   82.52 -            + "  @net.java.html.geo.OnLocation\n"
   82.53 -            + "  private static void cantCallMe(net.java.html.geo.Position p) {}\n"
   82.54 -            + "}\n"
   82.55 -        );
   82.56 -        res.assertErrors();
   82.57 -        res.assertError("cannot be private");
   82.58 -    }
   82.59 -    
   82.60 -    @Test public void onErrorHasToExist() throws IOException {
   82.61 -        Compile res = Compile.create("", "package x;\n"
   82.62 -            + "class UseOnLocation {\n"
   82.63 -            + "  @net.java.html.geo.OnLocation(onError=\"doesNotExist\")\n"
   82.64 -            + "  static void cantCallMe(net.java.html.geo.Position p) {}\n"
   82.65 -            + "}\n"
   82.66 -        );
   82.67 -        res.assertErrors();
   82.68 -        res.assertError("not find doesNotExist");
   82.69 -    }
   82.70 -
   82.71 -    @Test public void onErrorWouldHaveToBeStatic() throws IOException {
   82.72 -        Compile res = Compile.create("", "package x;\n"
   82.73 -            + "class UseOnLocation {\n"
   82.74 -            + "  @net.java.html.geo.OnLocation(onError=\"notStatic\")\n"
   82.75 -            + "  static void cantCallMe(net.java.html.geo.Position p) {}\n"
   82.76 -            + "  void notStatic(Exception e) {}\n"
   82.77 -            + "}\n"
   82.78 -        );
   82.79 -        res.assertErrors();
   82.80 -        res.assertError("have to be static");
   82.81 -    }
   82.82 -
   82.83 -    @Test public void onErrorMustAcceptExceptionArgument() throws IOException {
   82.84 -        Compile res = Compile.create("", "package x;\n"
   82.85 -            + "class UseOnLocation {\n"
   82.86 -            + "  @net.java.html.geo.OnLocation(onError=\"notStatic\")\n"
   82.87 -            + "  static void cantCallMe(net.java.html.geo.Position p) {}\n"
   82.88 -            + "  static void notStatic(java.io.IOException e) {}\n"
   82.89 -            + "}\n"
   82.90 -        );
   82.91 -        res.assertErrors();
   82.92 -        res.assertError("Error method first argument needs to be Exception");
   82.93 -    }
   82.94 -    
   82.95 -}
    83.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    83.2 +++ b/geo/src/test/java/org/netbeans/html/geo/impl/Compile.java	Mon Dec 16 17:16:40 2013 +0100
    83.3 @@ -0,0 +1,286 @@
    83.4 +/**
    83.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    83.6 + *
    83.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    83.8 + *
    83.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   83.10 + * Other names may be trademarks of their respective owners.
   83.11 + *
   83.12 + * The contents of this file are subject to the terms of either the GNU
   83.13 + * General Public License Version 2 only ("GPL") or the Common
   83.14 + * Development and Distribution License("CDDL") (collectively, the
   83.15 + * "License"). You may not use this file except in compliance with the
   83.16 + * License. You can obtain a copy of the License at
   83.17 + * http://www.netbeans.org/cddl-gplv2.html
   83.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   83.19 + * specific language governing permissions and limitations under the
   83.20 + * License.  When distributing the software, include this License Header
   83.21 + * Notice in each file and include the License file at
   83.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   83.23 + * particular file as subject to the "Classpath" exception as provided
   83.24 + * by Oracle in the GPL Version 2 section of the License file that
   83.25 + * accompanied this code. If applicable, add the following below the
   83.26 + * License Header, with the fields enclosed by brackets [] replaced by
   83.27 + * your own identifying information:
   83.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   83.29 + *
   83.30 + * Contributor(s):
   83.31 + *
   83.32 + * The Original Software is NetBeans. The Initial Developer of the Original
   83.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   83.34 + *
   83.35 + * If you wish your version of this file to be governed by only the CDDL
   83.36 + * or only the GPL Version 2, indicate your decision by adding
   83.37 + * "[Contributor] elects to include this software in this distribution
   83.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   83.39 + * single choice of license, a recipient has the option to distribute
   83.40 + * your version of this file under either the CDDL, the GPL Version 2 or
   83.41 + * to extend the choice of license to its licensees as provided above.
   83.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   83.43 + * Version 2 license, then the option applies only if the new code is
   83.44 + * made subject to such option by the copyright holder.
   83.45 + */
   83.46 +package org.netbeans.html.geo.impl;
   83.47 +
   83.48 +import java.io.ByteArrayInputStream;
   83.49 +import java.io.ByteArrayOutputStream;
   83.50 +import java.io.IOException;
   83.51 +import java.io.InputStream;
   83.52 +import java.io.OutputStream;
   83.53 +import java.net.URI;
   83.54 +import java.net.URISyntaxException;
   83.55 +import java.util.ArrayList;
   83.56 +import java.util.Arrays;
   83.57 +import java.util.HashMap;
   83.58 +import java.util.List;
   83.59 +import java.util.Locale;
   83.60 +import java.util.Map;
   83.61 +import java.util.regex.Matcher;
   83.62 +import java.util.regex.Pattern;
   83.63 +import javax.tools.Diagnostic;
   83.64 +import javax.tools.DiagnosticListener;
   83.65 +import javax.tools.FileObject;
   83.66 +import javax.tools.ForwardingJavaFileManager;
   83.67 +import javax.tools.JavaFileManager;
   83.68 +import javax.tools.JavaFileObject;
   83.69 +import javax.tools.JavaFileObject.Kind;
   83.70 +import javax.tools.SimpleJavaFileObject;
   83.71 +import javax.tools.StandardJavaFileManager;
   83.72 +import javax.tools.StandardLocation;
   83.73 +import javax.tools.ToolProvider;
   83.74 +import static org.testng.Assert.*;
   83.75 +
   83.76 +/**
   83.77 + *
   83.78 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   83.79 + */
   83.80 +final class Compile implements DiagnosticListener<JavaFileObject> {
   83.81 +    private final List<Diagnostic<? extends JavaFileObject>> errors = 
   83.82 +            new ArrayList<Diagnostic<? extends JavaFileObject>>();
   83.83 +    private final Map<String, byte[]> classes;
   83.84 +    private final String pkg;
   83.85 +    private final String cls;
   83.86 +    private final String html;
   83.87 +    private final String sourceLevel;
   83.88 +
   83.89 +    private Compile(String html, String code, String sl) throws IOException {
   83.90 +        this.pkg = findPkg(code);
   83.91 +        this.cls = findCls(code);
   83.92 +        this.html = html;
   83.93 +        this.sourceLevel = sl;
   83.94 +        classes = compile(html, code);
   83.95 +    }
   83.96 +
   83.97 +    /** Performs compilation of given HTML page and associated Java code
   83.98 +     */
   83.99 +    public static Compile create(String html, String code) throws IOException {
  83.100 +        return create(html, code, "1.7");
  83.101 +    }
  83.102 +    static Compile create(String html, String code, String sourceLevel) throws IOException {
  83.103 +        return new Compile(html, code, sourceLevel);
  83.104 +    }
  83.105 +    
  83.106 +    /** Checks for given class among compiled resources */
  83.107 +    public byte[] get(String res) {
  83.108 +        return classes.get(res);
  83.109 +    }
  83.110 +    
  83.111 +    /** Obtains errors created during compilation.
  83.112 +     */
  83.113 +    public List<Diagnostic<? extends JavaFileObject>> getErrors() {
  83.114 +        List<Diagnostic<? extends JavaFileObject>> err;
  83.115 +        err = new ArrayList<Diagnostic<? extends JavaFileObject>>();
  83.116 +        for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
  83.117 +            if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
  83.118 +                err.add(diagnostic);
  83.119 +            }
  83.120 +        }
  83.121 +        return err;
  83.122 +    }
  83.123 +    
  83.124 +    private Map<String, byte[]> compile(final String html, final String code) throws IOException {
  83.125 +        StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
  83.126 +
  83.127 +        final Map<String, ByteArrayOutputStream> class2BAOS;
  83.128 +        class2BAOS = new HashMap<String, ByteArrayOutputStream>();
  83.129 +
  83.130 +        JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
  83.131 +            @Override
  83.132 +            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  83.133 +                return code;
  83.134 +            }
  83.135 +        };
  83.136 +        final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
  83.137 +            @Override
  83.138 +            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  83.139 +                return html;
  83.140 +            }
  83.141 +
  83.142 +            @Override
  83.143 +            public InputStream openInputStream() throws IOException {
  83.144 +                return new ByteArrayInputStream(html.getBytes());
  83.145 +            }
  83.146 +        };
  83.147 +        
  83.148 +        final URI scratch;
  83.149 +        try {
  83.150 +            scratch = new URI("mem://mem3");
  83.151 +        } catch (URISyntaxException ex) {
  83.152 +            throw new IOException(ex);
  83.153 +        }
  83.154 +        
  83.155 +        JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
  83.156 +            @Override
  83.157 +            public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
  83.158 +                if (kind  == Kind.CLASS) {
  83.159 +                    final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
  83.160 +
  83.161 +                    class2BAOS.put(className.replace('.', '/') + ".class", buffer);
  83.162 +                    return new SimpleJavaFileObject(sibling.toUri(), kind) {
  83.163 +                        @Override
  83.164 +                        public OutputStream openOutputStream() throws IOException {
  83.165 +                            return buffer;
  83.166 +                        }
  83.167 +                    };
  83.168 +                }
  83.169 +                
  83.170 +                if (kind == Kind.SOURCE) {
  83.171 +                    final String n = className.replace('.', '/') + ".java";
  83.172 +                    final URI un;
  83.173 +                    try {
  83.174 +                        un = new URI("mem://" + n);
  83.175 +                    } catch (URISyntaxException ex) {
  83.176 +                        throw new IOException(ex);
  83.177 +                    }
  83.178 +                    return new VirtFO(un/*sibling.toUri()*/, kind, n);
  83.179 +                }
  83.180 +                
  83.181 +                throw new IllegalStateException();
  83.182 +            }
  83.183 +
  83.184 +            @Override
  83.185 +            public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
  83.186 +                if (location == StandardLocation.SOURCE_PATH) {
  83.187 +                    if (packageName.equals(pkg)) {
  83.188 +                        return htmlFile;
  83.189 +                    }
  83.190 +                }
  83.191 +                
  83.192 +                return null;
  83.193 +            }
  83.194 +
  83.195 +            @Override
  83.196 +            public boolean isSameFile(FileObject a, FileObject b) {
  83.197 +                if (a instanceof VirtFO && b instanceof VirtFO) {
  83.198 +                    return ((VirtFO)a).getName().equals(((VirtFO)b).getName());
  83.199 +                }
  83.200 +                
  83.201 +                return super.isSameFile(a, b);
  83.202 +            }
  83.203 +
  83.204 +            class VirtFO extends SimpleJavaFileObject {
  83.205 +
  83.206 +                private final String n;
  83.207 +
  83.208 +                public VirtFO(URI uri, Kind kind, String n) {
  83.209 +                    super(uri, kind);
  83.210 +                    this.n = n;
  83.211 +                }
  83.212 +                private final ByteArrayOutputStream data = new ByteArrayOutputStream();
  83.213 +
  83.214 +                @Override
  83.215 +                public OutputStream openOutputStream() throws IOException {
  83.216 +                    return data;
  83.217 +                }
  83.218 +
  83.219 +                @Override
  83.220 +                public String getName() {
  83.221 +                    return n;
  83.222 +                }
  83.223 +
  83.224 +                @Override
  83.225 +                public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  83.226 +                    data.close();
  83.227 +                    return new String(data.toByteArray());
  83.228 +                }
  83.229 +            }
  83.230 +        };
  83.231 +
  83.232 +        ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", sourceLevel, "-target", "1.7"), null, Arrays.asList(file)).call();
  83.233 +
  83.234 +        Map<String, byte[]> result = new HashMap<String, byte[]>();
  83.235 +
  83.236 +        for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
  83.237 +            result.put(e.getKey(), e.getValue().toByteArray());
  83.238 +        }
  83.239 +
  83.240 +        return result;
  83.241 +    }
  83.242 +
  83.243 +
  83.244 +    @Override
  83.245 +    public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
  83.246 +        errors.add(diagnostic);
  83.247 +    }
  83.248 +    private static String findPkg(String java) throws IOException {
  83.249 +        Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
  83.250 +        Matcher m = p.matcher(java);
  83.251 +        if (!m.find()) {
  83.252 +            throw new IOException("Can't find package declaration in the java file");
  83.253 +        }
  83.254 +        String pkg = m.group(1);
  83.255 +        return pkg;
  83.256 +    }
  83.257 +    private static String findCls(String java) throws IOException {
  83.258 +        Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
  83.259 +        Matcher m = p.matcher(java);
  83.260 +        if (!m.find()) {
  83.261 +            throw new IOException("Can't find package declaration in the java file");
  83.262 +        }
  83.263 +        String cls = m.group(1);
  83.264 +        return cls;
  83.265 +    }
  83.266 +
  83.267 +    String getHtml() {
  83.268 +        String fqn = "'" + pkg + '.' + cls + "'";
  83.269 +        return html.replace("'${fqn}'", fqn);
  83.270 +    }
  83.271 +
  83.272 +    void assertErrors() {
  83.273 +        assertFalse(getErrors().isEmpty(), "There are supposed to be some errors");
  83.274 +    }
  83.275 +
  83.276 +    void assertError(String expMsg) {
  83.277 +        StringBuilder sb = new StringBuilder();
  83.278 +        sb.append("Can't find ").append(expMsg).append(" among:");
  83.279 +        for (Diagnostic<? extends JavaFileObject> e : errors) {
  83.280 +            String msg = e.getMessage(Locale.US);
  83.281 +            if (msg.contains(expMsg)) {
  83.282 +                return;
  83.283 +            }
  83.284 +            sb.append("\n");
  83.285 +            sb.append(msg);
  83.286 +        }
  83.287 +        fail(sb.toString());
  83.288 +    }
  83.289 +}
    84.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    84.2 +++ b/geo/src/test/java/org/netbeans/html/geo/impl/GeoProcessorTest.java	Mon Dec 16 17:16:40 2013 +0100
    84.3 @@ -0,0 +1,114 @@
    84.4 +/**
    84.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    84.6 + *
    84.7 + * Copyright 1997-2010 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 org.testng.annotations.Test;
   84.50 +
   84.51 +/** Test whether the annotation processor detects errors correctly.
   84.52 + *
   84.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   84.54 + */
   84.55 +public class GeoProcessorTest {
   84.56 +    
   84.57 +    public GeoProcessorTest() {
   84.58 +    }
   84.59 +
   84.60 +    @Test public void onLocationMethodHasToTakePositionParameter() throws IOException {
   84.61 +        Compile res = Compile.create("", "package x;\n"
   84.62 +            + "class UseOnLocation {\n"
   84.63 +            + "  @net.java.html.geo.OnLocation\n"
   84.64 +            + "  public static void cantCallMe() {}\n"
   84.65 +            + "}\n"
   84.66 +        );
   84.67 +        res.assertErrors();
   84.68 +        res.assertError("first argument must be net.java.html.geo.Position");
   84.69 +    }
   84.70 +    
   84.71 +    @Test public void onLocationMethodCannotBePrivate() throws IOException {
   84.72 +        Compile res = Compile.create("", "package x;\n"
   84.73 +            + "class UseOnLocation {\n"
   84.74 +            + "  @net.java.html.geo.OnLocation\n"
   84.75 +            + "  private static void cantCallMe(net.java.html.geo.Position p) {}\n"
   84.76 +            + "}\n"
   84.77 +        );
   84.78 +        res.assertErrors();
   84.79 +        res.assertError("cannot be private");
   84.80 +    }
   84.81 +    
   84.82 +    @Test public void onErrorHasToExist() throws IOException {
   84.83 +        Compile res = Compile.create("", "package x;\n"
   84.84 +            + "class UseOnLocation {\n"
   84.85 +            + "  @net.java.html.geo.OnLocation(onError=\"doesNotExist\")\n"
   84.86 +            + "  static void cantCallMe(net.java.html.geo.Position p) {}\n"
   84.87 +            + "}\n"
   84.88 +        );
   84.89 +        res.assertErrors();
   84.90 +        res.assertError("not find doesNotExist");
   84.91 +    }
   84.92 +
   84.93 +    @Test public void onErrorWouldHaveToBeStatic() throws IOException {
   84.94 +        Compile res = Compile.create("", "package x;\n"
   84.95 +            + "class UseOnLocation {\n"
   84.96 +            + "  @net.java.html.geo.OnLocation(onError=\"notStatic\")\n"
   84.97 +            + "  static void cantCallMe(net.java.html.geo.Position p) {}\n"
   84.98 +            + "  void notStatic(Exception e) {}\n"
   84.99 +            + "}\n"
  84.100 +        );
  84.101 +        res.assertErrors();
  84.102 +        res.assertError("have to be static");
  84.103 +    }
  84.104 +
  84.105 +    @Test public void onErrorMustAcceptExceptionArgument() throws IOException {
  84.106 +        Compile res = Compile.create("", "package x;\n"
  84.107 +            + "class UseOnLocation {\n"
  84.108 +            + "  @net.java.html.geo.OnLocation(onError=\"notStatic\")\n"
  84.109 +            + "  static void cantCallMe(net.java.html.geo.Position p) {}\n"
  84.110 +            + "  static void notStatic(java.io.IOException e) {}\n"
  84.111 +            + "}\n"
  84.112 +        );
  84.113 +        res.assertErrors();
  84.114 +        res.assertError("Error method first argument needs to be Exception");
  84.115 +    }
  84.116 +    
  84.117 +}
    85.1 --- a/json-tck/pom.xml	Mon Dec 16 17:16:02 2013 +0100
    85.2 +++ b/json-tck/pom.xml	Mon Dec 16 17:16:40 2013 +0100
    85.3 @@ -2,11 +2,11 @@
    85.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">
    85.5    <modelVersion>4.0.0</modelVersion>
    85.6    <parent>
    85.7 -    <groupId>org.apidesign</groupId>
    85.8 -    <artifactId>html</artifactId>
    85.9 +    <groupId>org.netbeans.html</groupId>
   85.10 +    <artifactId>pom</artifactId>
   85.11      <version>0.7-SNAPSHOT</version>
   85.12    </parent>
   85.13 -  <groupId>org.apidesign.html</groupId>
   85.14 +  <groupId>org.netbeans.html</groupId>
   85.15    <artifactId>net.java.html.json.tck</artifactId>
   85.16    <version>0.7-SNAPSHOT</version>
   85.17    <packaging>bundle</packaging>
   85.18 @@ -35,7 +35,7 @@
   85.19    </build>
   85.20    <dependencies>
   85.21      <dependency>
   85.22 -      <groupId>org.apidesign.html</groupId>
   85.23 +      <groupId>org.netbeans.html</groupId>
   85.24        <artifactId>net.java.html.json</artifactId>
   85.25        <version>0.7-SNAPSHOT</version>
   85.26        <type>jar</type>
    86.1 --- a/json-tck/src/main/java/net/java/html/json/tests/ConvertTypesTest.java	Mon Dec 16 17:16:02 2013 +0100
    86.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/ConvertTypesTest.java	Mon Dec 16 17:16:40 2013 +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 1997-2010 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.json.tests;
   86.62  
   86.63 @@ -27,7 +49,7 @@
   86.64  import java.util.Map;
   86.65  import net.java.html.BrwsrCtx;
   86.66  import net.java.html.json.Models;
   86.67 -import org.apidesign.html.json.impl.JSON;
   86.68 +import org.netbeans.html.json.impl.JSON;
   86.69  import org.apidesign.html.json.tck.KOTest;
   86.70  
   86.71  /**
    87.1 --- a/json-tck/src/main/java/net/java/html/json/tests/JSONTest.java	Mon Dec 16 17:16:02 2013 +0100
    87.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/JSONTest.java	Mon Dec 16 17:16:40 2013 +0100
    87.3 @@ -1,22 +1,44 @@
    87.4  /**
    87.5 - * HTML via Java(tm) Language Bindings
    87.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    87.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    87.8   *
    87.9 - * This program is free software: you can redistribute it and/or modify
   87.10 - * it under the terms of the GNU General Public License as published by
   87.11 - * the Free Software Foundation, version 2 of the License.
   87.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   87.13   *
   87.14 - * This program is distributed in the hope that it will be useful,
   87.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   87.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   87.17 - * GNU General Public License for more details. apidesign.org
   87.18 - * designates this particular file as subject to the
   87.19 - * "Classpath" exception as provided by apidesign.org
   87.20 - * in the License file that accompanied this code.
   87.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   87.22 + * Other names may be trademarks of their respective owners.
   87.23   *
   87.24 - * You should have received a copy of the GNU General Public License
   87.25 - * along with this program. Look for COPYING file in the top folder.
   87.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   87.27 + * The contents of this file are subject to the terms of either the GNU
   87.28 + * General Public License Version 2 only ("GPL") or the Common
   87.29 + * Development and Distribution License("CDDL") (collectively, the
   87.30 + * "License"). You may not use this file except in compliance with the
   87.31 + * License. You can obtain a copy of the License at
   87.32 + * http://www.netbeans.org/cddl-gplv2.html
   87.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   87.34 + * specific language governing permissions and limitations under the
   87.35 + * License.  When distributing the software, include this License Header
   87.36 + * Notice in each file and include the License file at
   87.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   87.38 + * particular file as subject to the "Classpath" exception as provided
   87.39 + * by Oracle in the GPL Version 2 section of the License file that
   87.40 + * accompanied this code. If applicable, add the following below the
   87.41 + * License Header, with the fields enclosed by brackets [] replaced by
   87.42 + * your own identifying information:
   87.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   87.44 + *
   87.45 + * Contributor(s):
   87.46 + *
   87.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   87.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   87.49 + *
   87.50 + * If you wish your version of this file to be governed by only the CDDL
   87.51 + * or only the GPL Version 2, indicate your decision by adding
   87.52 + * "[Contributor] elects to include this software in this distribution
   87.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   87.54 + * single choice of license, a recipient has the option to distribute
   87.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   87.56 + * to extend the choice of license to its licensees as provided above.
   87.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   87.58 + * Version 2 license, then the option applies only if the new code is
   87.59 + * made subject to such option by the copyright holder.
   87.60   */
   87.61  package net.java.html.json.tests;
   87.62  
   87.63 @@ -27,7 +49,7 @@
   87.64  import net.java.html.json.Models;
   87.65  import net.java.html.json.OnReceive;
   87.66  import net.java.html.json.Property;
   87.67 -import org.apidesign.html.json.impl.JSON;
   87.68 +import org.netbeans.html.json.impl.JSON;
   87.69  import org.apidesign.html.json.tck.KOTest;
   87.70  
   87.71  /** Need to verify that models produce reasonable JSON objects.
    88.1 --- a/json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java	Mon Dec 16 17:16:02 2013 +0100
    88.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java	Mon Dec 16 17:16:40 2013 +0100
    88.3 @@ -1,22 +1,44 @@
    88.4  /**
    88.5 - * HTML via Java(tm) Language Bindings
    88.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    88.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    88.8   *
    88.9 - * This program is free software: you can redistribute it and/or modify
   88.10 - * it under the terms of the GNU General Public License as published by
   88.11 - * the Free Software Foundation, version 2 of the License.
   88.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   88.13   *
   88.14 - * This program is distributed in the hope that it will be useful,
   88.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   88.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   88.17 - * GNU General Public License for more details. apidesign.org
   88.18 - * designates this particular file as subject to the
   88.19 - * "Classpath" exception as provided by apidesign.org
   88.20 - * in the License file that accompanied this code.
   88.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   88.22 + * Other names may be trademarks of their respective owners.
   88.23   *
   88.24 - * You should have received a copy of the GNU General Public License
   88.25 - * along with this program. Look for COPYING file in the top folder.
   88.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   88.27 + * The contents of this file are subject to the terms of either the GNU
   88.28 + * General Public License Version 2 only ("GPL") or the Common
   88.29 + * Development and Distribution License("CDDL") (collectively, the
   88.30 + * "License"). You may not use this file except in compliance with the
   88.31 + * License. You can obtain a copy of the License at
   88.32 + * http://www.netbeans.org/cddl-gplv2.html
   88.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   88.34 + * specific language governing permissions and limitations under the
   88.35 + * License.  When distributing the software, include this License Header
   88.36 + * Notice in each file and include the License file at
   88.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   88.38 + * particular file as subject to the "Classpath" exception as provided
   88.39 + * by Oracle in the GPL Version 2 section of the License file that
   88.40 + * accompanied this code. If applicable, add the following below the
   88.41 + * License Header, with the fields enclosed by brackets [] replaced by
   88.42 + * your own identifying information:
   88.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   88.44 + *
   88.45 + * Contributor(s):
   88.46 + *
   88.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   88.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   88.49 + *
   88.50 + * If you wish your version of this file to be governed by only the CDDL
   88.51 + * or only the GPL Version 2, indicate your decision by adding
   88.52 + * "[Contributor] elects to include this software in this distribution
   88.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   88.54 + * single choice of license, a recipient has the option to distribute
   88.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   88.56 + * to extend the choice of license to its licensees as provided above.
   88.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   88.58 + * Version 2 license, then the option applies only if the new code is
   88.59 + * made subject to such option by the copyright holder.
   88.60   */
   88.61  package net.java.html.json.tests;
   88.62  
    89.1 --- a/json-tck/src/main/java/net/java/html/json/tests/OperationsTest.java	Mon Dec 16 17:16:02 2013 +0100
    89.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/OperationsTest.java	Mon Dec 16 17:16:40 2013 +0100
    89.3 @@ -1,22 +1,44 @@
    89.4  /**
    89.5 - * HTML via Java(tm) Language Bindings
    89.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    89.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    89.8   *
    89.9 - * This program is free software: you can redistribute it and/or modify
   89.10 - * it under the terms of the GNU General Public License as published by
   89.11 - * the Free Software Foundation, version 2 of the License.
   89.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   89.13   *
   89.14 - * This program is distributed in the hope that it will be useful,
   89.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   89.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   89.17 - * GNU General Public License for more details. apidesign.org
   89.18 - * designates this particular file as subject to the
   89.19 - * "Classpath" exception as provided by apidesign.org
   89.20 - * in the License file that accompanied this code.
   89.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   89.22 + * Other names may be trademarks of their respective owners.
   89.23   *
   89.24 - * You should have received a copy of the GNU General Public License
   89.25 - * along with this program. Look for COPYING file in the top folder.
   89.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   89.27 + * The contents of this file are subject to the terms of either the GNU
   89.28 + * General Public License Version 2 only ("GPL") or the Common
   89.29 + * Development and Distribution License("CDDL") (collectively, the
   89.30 + * "License"). You may not use this file except in compliance with the
   89.31 + * License. You can obtain a copy of the License at
   89.32 + * http://www.netbeans.org/cddl-gplv2.html
   89.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   89.34 + * specific language governing permissions and limitations under the
   89.35 + * License.  When distributing the software, include this License Header
   89.36 + * Notice in each file and include the License file at
   89.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   89.38 + * particular file as subject to the "Classpath" exception as provided
   89.39 + * by Oracle in the GPL Version 2 section of the License file that
   89.40 + * accompanied this code. If applicable, add the following below the
   89.41 + * License Header, with the fields enclosed by brackets [] replaced by
   89.42 + * your own identifying information:
   89.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   89.44 + *
   89.45 + * Contributor(s):
   89.46 + *
   89.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   89.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   89.49 + *
   89.50 + * If you wish your version of this file to be governed by only the CDDL
   89.51 + * or only the GPL Version 2, indicate your decision by adding
   89.52 + * "[Contributor] elects to include this software in this distribution
   89.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   89.54 + * single choice of license, a recipient has the option to distribute
   89.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   89.56 + * to extend the choice of license to its licensees as provided above.
   89.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   89.58 + * Version 2 license, then the option applies only if the new code is
   89.59 + * made subject to such option by the copyright holder.
   89.60   */
   89.61  package net.java.html.json.tests;
   89.62  
    90.1 --- a/json-tck/src/main/java/net/java/html/json/tests/PairModel.java	Mon Dec 16 17:16:02 2013 +0100
    90.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/PairModel.java	Mon Dec 16 17:16:40 2013 +0100
    90.3 @@ -1,22 +1,44 @@
    90.4  /**
    90.5 - * HTML via Java(tm) Language Bindings
    90.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    90.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    90.8   *
    90.9 - * This program is free software: you can redistribute it and/or modify
   90.10 - * it under the terms of the GNU General Public License as published by
   90.11 - * the Free Software Foundation, version 2 of the License.
   90.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   90.13   *
   90.14 - * This program is distributed in the hope that it will be useful,
   90.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   90.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   90.17 - * GNU General Public License for more details. apidesign.org
   90.18 - * designates this particular file as subject to the
   90.19 - * "Classpath" exception as provided by apidesign.org
   90.20 - * in the License file that accompanied this code.
   90.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   90.22 + * Other names may be trademarks of their respective owners.
   90.23   *
   90.24 - * You should have received a copy of the GNU General Public License
   90.25 - * along with this program. Look for COPYING file in the top folder.
   90.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   90.27 + * The contents of this file are subject to the terms of either the GNU
   90.28 + * General Public License Version 2 only ("GPL") or the Common
   90.29 + * Development and Distribution License("CDDL") (collectively, the
   90.30 + * "License"). You may not use this file except in compliance with the
   90.31 + * License. You can obtain a copy of the License at
   90.32 + * http://www.netbeans.org/cddl-gplv2.html
   90.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   90.34 + * specific language governing permissions and limitations under the
   90.35 + * License.  When distributing the software, include this License Header
   90.36 + * Notice in each file and include the License file at
   90.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   90.38 + * particular file as subject to the "Classpath" exception as provided
   90.39 + * by Oracle in the GPL Version 2 section of the License file that
   90.40 + * accompanied this code. If applicable, add the following below the
   90.41 + * License Header, with the fields enclosed by brackets [] replaced by
   90.42 + * your own identifying information:
   90.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   90.44 + *
   90.45 + * Contributor(s):
   90.46 + *
   90.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   90.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   90.49 + *
   90.50 + * If you wish your version of this file to be governed by only the CDDL
   90.51 + * or only the GPL Version 2, indicate your decision by adding
   90.52 + * "[Contributor] elects to include this software in this distribution
   90.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   90.54 + * single choice of license, a recipient has the option to distribute
   90.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   90.56 + * to extend the choice of license to its licensees as provided above.
   90.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   90.58 + * Version 2 license, then the option applies only if the new code is
   90.59 + * made subject to such option by the copyright holder.
   90.60   */
   90.61  package net.java.html.json.tests;
   90.62  
    91.1 --- a/json-tck/src/main/java/net/java/html/json/tests/PersonImpl.java	Mon Dec 16 17:16:02 2013 +0100
    91.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/PersonImpl.java	Mon Dec 16 17:16:40 2013 +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 1997-2010 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 net.java.html.json.tests;
   91.62  
    92.1 --- a/json-tck/src/main/java/net/java/html/json/tests/Sex.java	Mon Dec 16 17:16:02 2013 +0100
    92.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/Sex.java	Mon Dec 16 17:16:40 2013 +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 1997-2010 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 net.java.html.json.tests;
   92.62  
    93.1 --- a/json-tck/src/main/java/net/java/html/json/tests/Utils.java	Mon Dec 16 17:16:02 2013 +0100
    93.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/Utils.java	Mon Dec 16 17:16:40 2013 +0100
    93.3 @@ -1,22 +1,44 @@
    93.4  /**
    93.5 - * HTML via Java(tm) Language Bindings
    93.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    93.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    93.8   *
    93.9 - * This program is free software: you can redistribute it and/or modify
   93.10 - * it under the terms of the GNU General Public License as published by
   93.11 - * the Free Software Foundation, version 2 of the License.
   93.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   93.13   *
   93.14 - * This program is distributed in the hope that it will be useful,
   93.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   93.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   93.17 - * GNU General Public License for more details. apidesign.org
   93.18 - * designates this particular file as subject to the
   93.19 - * "Classpath" exception as provided by apidesign.org
   93.20 - * in the License file that accompanied this code.
   93.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   93.22 + * Other names may be trademarks of their respective owners.
   93.23   *
   93.24 - * You should have received a copy of the GNU General Public License
   93.25 - * along with this program. Look for COPYING file in the top folder.
   93.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   93.27 + * The contents of this file are subject to the terms of either the GNU
   93.28 + * General Public License Version 2 only ("GPL") or the Common
   93.29 + * Development and Distribution License("CDDL") (collectively, the
   93.30 + * "License"). You may not use this file except in compliance with the
   93.31 + * License. You can obtain a copy of the License at
   93.32 + * http://www.netbeans.org/cddl-gplv2.html
   93.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   93.34 + * specific language governing permissions and limitations under the
   93.35 + * License.  When distributing the software, include this License Header
   93.36 + * Notice in each file and include the License file at
   93.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   93.38 + * particular file as subject to the "Classpath" exception as provided
   93.39 + * by Oracle in the GPL Version 2 section of the License file that
   93.40 + * accompanied this code. If applicable, add the following below the
   93.41 + * License Header, with the fields enclosed by brackets [] replaced by
   93.42 + * your own identifying information:
   93.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   93.44 + *
   93.45 + * Contributor(s):
   93.46 + *
   93.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   93.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   93.49 + *
   93.50 + * If you wish your version of this file to be governed by only the CDDL
   93.51 + * or only the GPL Version 2, indicate your decision by adding
   93.52 + * "[Contributor] elects to include this software in this distribution
   93.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   93.54 + * single choice of license, a recipient has the option to distribute
   93.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   93.56 + * to extend the choice of license to its licensees as provided above.
   93.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   93.58 + * Version 2 license, then the option applies only if the new code is
   93.59 + * made subject to such option by the copyright holder.
   93.60   */
   93.61  package net.java.html.json.tests;
   93.62  
    94.1 --- a/json-tck/src/main/java/net/java/html/json/tests/WebSocketTest.java	Mon Dec 16 17:16:02 2013 +0100
    94.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/WebSocketTest.java	Mon Dec 16 17:16:40 2013 +0100
    94.3 @@ -1,22 +1,44 @@
    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 1997-2010 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  package net.java.html.json.tests;
   94.62  
    95.1 --- a/json-tck/src/main/java/org/apidesign/html/json/tck/KOTest.java	Mon Dec 16 17:16:02 2013 +0100
    95.2 +++ b/json-tck/src/main/java/org/apidesign/html/json/tck/KOTest.java	Mon Dec 16 17:16:40 2013 +0100
    95.3 @@ -1,22 +1,44 @@
    95.4  /**
    95.5 - * HTML via Java(tm) Language Bindings
    95.6 - * Copyright (C) 2013 Jaroslav Tulach <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
   95.10 - * it under the terms of the GNU General Public License as published by
   95.11 - * the Free Software Foundation, version 2 of the License.
   95.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   95.13   *
   95.14 - * This program is distributed in the hope that it will be useful,
   95.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   95.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   95.17 - * GNU General Public License for more details. apidesign.org
   95.18 - * designates this particular file as subject to the
   95.19 - * "Classpath" exception as provided by apidesign.org
   95.20 - * in the License file that accompanied this code.
   95.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   95.22 + * Other names may be trademarks of their respective owners.
   95.23   *
   95.24 - * You should have received a copy of the GNU General Public License
   95.25 - * along with this program. Look for COPYING file in the top folder.
   95.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   95.27 + * The contents of this file are subject to the terms of either the GNU
   95.28 + * General Public License Version 2 only ("GPL") or the Common
   95.29 + * Development and Distribution License("CDDL") (collectively, the
   95.30 + * "License"). You may not use this file except in compliance with the
   95.31 + * License. You can obtain a copy of the License at
   95.32 + * http://www.netbeans.org/cddl-gplv2.html
   95.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   95.34 + * specific language governing permissions and limitations under the
   95.35 + * License.  When distributing the software, include this License Header
   95.36 + * Notice in each file and include the License file at
   95.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   95.38 + * particular file as subject to the "Classpath" exception as provided
   95.39 + * by Oracle in the GPL Version 2 section of the License file that
   95.40 + * accompanied this code. If applicable, add the following below the
   95.41 + * License Header, with the fields enclosed by brackets [] replaced by
   95.42 + * your own identifying information:
   95.43 + * "Portions Copyrighted [year] [name of copyright owner]"
   95.44 + *
   95.45 + * Contributor(s):
   95.46 + *
   95.47 + * The Original Software is NetBeans. The Initial Developer of the Original
   95.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   95.49 + *
   95.50 + * If you wish your version of this file to be governed by only the CDDL
   95.51 + * or only the GPL Version 2, indicate your decision by adding
   95.52 + * "[Contributor] elects to include this software in this distribution
   95.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   95.54 + * single choice of license, a recipient has the option to distribute
   95.55 + * your version of this file under either the CDDL, the GPL Version 2 or
   95.56 + * to extend the choice of license to its licensees as provided above.
   95.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   95.58 + * Version 2 license, then the option applies only if the new code is
   95.59 + * made subject to such option by the copyright holder.
   95.60   */
   95.61  package org.apidesign.html.json.tck;
   95.62  
    96.1 --- a/json-tck/src/main/java/org/apidesign/html/json/tck/KnockoutTCK.java	Mon Dec 16 17:16:02 2013 +0100
    96.2 +++ b/json-tck/src/main/java/org/apidesign/html/json/tck/KnockoutTCK.java	Mon Dec 16 17:16:40 2013 +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 1997-2010 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 org.apidesign.html.json.tck;
   96.62  
    97.1 --- a/json-tck/src/main/resources/org/apidesign/html/json/tck/package.html	Mon Dec 16 17:16:02 2013 +0100
    97.2 +++ b/json-tck/src/main/resources/org/apidesign/html/json/tck/package.html	Mon Dec 16 17:16:40 2013 +0100
    97.3 @@ -1,23 +1,45 @@
    97.4  <!--
    97.5  
    97.6 -    HTML via Java(tm) Language Bindings
    97.7 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    97.8 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    97.9  
   97.10 -    This program is free software: you can redistribute it and/or modify
   97.11 -    it under the terms of the GNU General Public License as published by
   97.12 -    the Free Software Foundation, version 2 of the License.
   97.13 +    Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   97.14  
   97.15 -    This program is distributed in the hope that it will be useful,
   97.16 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   97.17 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   97.18 -    GNU General Public License for more details. apidesign.org
   97.19 -    designates this particular file as subject to the
   97.20 -    "Classpath" exception as provided by apidesign.org
   97.21 -    in the License file that accompanied this code.
   97.22 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   97.23 +    Other names may be trademarks of their respective owners.
   97.24  
   97.25 -    You should have received a copy of the GNU General Public License
   97.26 -    along with this program. Look for COPYING file in the top folder.
   97.27 -    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   97.28 +    The contents of this file are subject to the terms of either the GNU
   97.29 +    General Public License Version 2 only ("GPL") or the Common
   97.30 +    Development and Distribution License("CDDL") (collectively, the
   97.31 +    "License"). You may not use this file except in compliance with the
   97.32 +    License. You can obtain a copy of the License at
   97.33 +    http://www.netbeans.org/cddl-gplv2.html
   97.34 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   97.35 +    specific language governing permissions and limitations under the
   97.36 +    License.  When distributing the software, include this License Header
   97.37 +    Notice in each file and include the License file at
   97.38 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   97.39 +    particular file as subject to the "Classpath" exception as provided
   97.40 +    by Oracle in the GPL Version 2 section of the License file that
   97.41 +    accompanied this code. If applicable, add the following below the
   97.42 +    License Header, with the fields enclosed by brackets [] replaced by
   97.43 +    your own identifying information:
   97.44 +    "Portions Copyrighted [year] [name of copyright owner]"
   97.45 +
   97.46 +    Contributor(s):
   97.47 +
   97.48 +    The Original Software is NetBeans. The Initial Developer of the Original
   97.49 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
   97.50 +
   97.51 +    If you wish your version of this file to be governed by only the CDDL
   97.52 +    or only the GPL Version 2, indicate your decision by adding
   97.53 +    "[Contributor] elects to include this software in this distribution
   97.54 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
   97.55 +    single choice of license, a recipient has the option to distribute
   97.56 +    your version of this file under either the CDDL, the GPL Version 2 or
   97.57 +    to extend the choice of license to its licensees as provided above.
   97.58 +    However, if you add GPL Version 2 code and therefore, elected the GPL
   97.59 +    Version 2 license, then the option applies only if the new code is
   97.60 +    made subject to such option by the copyright holder.
   97.61  
   97.62  -->
   97.63  <!DOCTYPE html>
    98.1 --- a/json/pom.xml	Mon Dec 16 17:16:02 2013 +0100
    98.2 +++ b/json/pom.xml	Mon Dec 16 17:16:40 2013 +0100
    98.3 @@ -2,11 +2,11 @@
    98.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">
    98.5    <modelVersion>4.0.0</modelVersion>
    98.6    <parent>
    98.7 -    <groupId>org.apidesign</groupId>
    98.8 -    <artifactId>html</artifactId>
    98.9 +    <groupId>org.netbeans.html</groupId>
   98.10 +    <artifactId>pom</artifactId>
   98.11      <version>0.7-SNAPSHOT</version>
   98.12    </parent>
   98.13 -  <groupId>org.apidesign.html</groupId>
   98.14 +  <groupId>org.netbeans.html</groupId>
   98.15    <artifactId>net.java.html.json</artifactId>
   98.16    <version>0.7-SNAPSHOT</version>
   98.17    <packaging>bundle</packaging>
    99.1 --- a/json/src/main/java/net/java/html/json/ComputedProperty.java	Mon Dec 16 17:16:02 2013 +0100
    99.2 +++ b/json/src/main/java/net/java/html/json/ComputedProperty.java	Mon Dec 16 17:16:40 2013 +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 1997-2010 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;
   99.62  
   100.1 --- a/json/src/main/java/net/java/html/json/Function.java	Mon Dec 16 17:16:02 2013 +0100
   100.2 +++ b/json/src/main/java/net/java/html/json/Function.java	Mon Dec 16 17:16:40 2013 +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 1997-2010 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;
  100.62  
   101.1 --- a/json/src/main/java/net/java/html/json/Model.java	Mon Dec 16 17:16:02 2013 +0100
   101.2 +++ b/json/src/main/java/net/java/html/json/Model.java	Mon Dec 16 17:16:40 2013 +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 1997-2010 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;
  101.62  
   102.1 --- a/json/src/main/java/net/java/html/json/ModelOperation.java	Mon Dec 16 17:16:02 2013 +0100
   102.2 +++ b/json/src/main/java/net/java/html/json/ModelOperation.java	Mon Dec 16 17:16:40 2013 +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 1997-2010 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;
  102.62  
   103.1 --- a/json/src/main/java/net/java/html/json/Models.java	Mon Dec 16 17:16:02 2013 +0100
   103.2 +++ b/json/src/main/java/net/java/html/json/Models.java	Mon Dec 16 17:16:40 2013 +0100
   103.3 @@ -1,29 +1,51 @@
   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 1997-2010 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;
  103.62  
  103.63  import net.java.html.BrwsrCtx;
  103.64  import java.io.IOException;
  103.65  import java.io.InputStream;
  103.66 -import org.apidesign.html.json.impl.JSON;
  103.67 +import org.netbeans.html.json.impl.JSON;
  103.68  
  103.69  /** Information about and 
  103.70   * operations for classes generated by the {@link Model @Model}
   104.1 --- a/json/src/main/java/net/java/html/json/OnPropertyChange.java	Mon Dec 16 17:16:02 2013 +0100
   104.2 +++ b/json/src/main/java/net/java/html/json/OnPropertyChange.java	Mon Dec 16 17:16:40 2013 +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 1997-2010 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;
  104.62  
   105.1 --- a/json/src/main/java/net/java/html/json/OnReceive.java	Mon Dec 16 17:16:02 2013 +0100
   105.2 +++ b/json/src/main/java/net/java/html/json/OnReceive.java	Mon Dec 16 17:16:40 2013 +0100
   105.3 @@ -1,22 +1,44 @@
   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 1997-2010 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;
  105.62  
   106.1 --- a/json/src/main/java/net/java/html/json/Property.java	Mon Dec 16 17:16:02 2013 +0100
   106.2 +++ b/json/src/main/java/net/java/html/json/Property.java	Mon Dec 16 17:16:40 2013 +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 1997-2010 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;
  106.62  
   107.1 --- a/json/src/main/java/net/java/html/json/doc-files/websockets.html	Mon Dec 16 17:16:02 2013 +0100
   107.2 +++ b/json/src/main/java/net/java/html/json/doc-files/websockets.html	Mon Dec 16 17:16:40 2013 +0100
   107.3 @@ -1,23 +1,45 @@
   107.4  <!--
   107.5  
   107.6 -    HTML via Java(tm) Language Bindings
   107.7 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   107.8 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   107.9  
  107.10 -    This program is free software: you can redistribute it and/or modify
  107.11 -    it under the terms of the GNU General Public License as published by
  107.12 -    the Free Software Foundation, version 2 of the License.
  107.13 +    Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  107.14  
  107.15 -    This program is distributed in the hope that it will be useful,
  107.16 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
  107.17 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  107.18 -    GNU General Public License for more details. apidesign.org
  107.19 -    designates this particular file as subject to the
  107.20 -    "Classpath" exception as provided by apidesign.org
  107.21 -    in the License file that accompanied this code.
  107.22 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  107.23 +    Other names may be trademarks of their respective owners.
  107.24  
  107.25 -    You should have received a copy of the GNU General Public License
  107.26 -    along with this program. Look for COPYING file in the top folder.
  107.27 -    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  107.28 +    The contents of this file are subject to the terms of either the GNU
  107.29 +    General Public License Version 2 only ("GPL") or the Common
  107.30 +    Development and Distribution License("CDDL") (collectively, the
  107.31 +    "License"). You may not use this file except in compliance with the
  107.32 +    License. You can obtain a copy of the License at
  107.33 +    http://www.netbeans.org/cddl-gplv2.html
  107.34 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  107.35 +    specific language governing permissions and limitations under the
  107.36 +    License.  When distributing the software, include this License Header
  107.37 +    Notice in each file and include the License file at
  107.38 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  107.39 +    particular file as subject to the "Classpath" exception as provided
  107.40 +    by Oracle in the GPL Version 2 section of the License file that
  107.41 +    accompanied this code. If applicable, add the following below the
  107.42 +    License Header, with the fields enclosed by brackets [] replaced by
  107.43 +    your own identifying information:
  107.44 +    "Portions Copyrighted [year] [name of copyright owner]"
  107.45 +
  107.46 +    Contributor(s):
  107.47 +
  107.48 +    The Original Software is NetBeans. The Initial Developer of the Original
  107.49 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  107.50 +
  107.51 +    If you wish your version of this file to be governed by only the CDDL
  107.52 +    or only the GPL Version 2, indicate your decision by adding
  107.53 +    "[Contributor] elects to include this software in this distribution
  107.54 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
  107.55 +    single choice of license, a recipient has the option to distribute
  107.56 +    your version of this file under either the CDDL, the GPL Version 2 or
  107.57 +    to extend the choice of license to its licensees as provided above.
  107.58 +    However, if you add GPL Version 2 code and therefore, elected the GPL
  107.59 +    Version 2 license, then the option applies only if the new code is
  107.60 +    made subject to such option by the copyright holder.
  107.61  
  107.62  -->
  107.63  <!DOCTYPE html>
   108.1 --- a/json/src/main/java/net/java/html/json/package.html	Mon Dec 16 17:16:02 2013 +0100
   108.2 +++ b/json/src/main/java/net/java/html/json/package.html	Mon Dec 16 17:16:40 2013 +0100
   108.3 @@ -1,23 +1,45 @@
   108.4  <!--
   108.5  
   108.6 -    HTML via Java(tm) Language Bindings
   108.7 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   108.8 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   108.9  
  108.10 -    This program is free software: you can redistribute it and/or modify
  108.11 -    it under the terms of the GNU General Public License as published by
  108.12 -    the Free Software Foundation, version 2 of the License.
  108.13 +    Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  108.14  
  108.15 -    This program is distributed in the hope that it will be useful,
  108.16 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
  108.17 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  108.18 -    GNU General Public License for more details. apidesign.org
  108.19 -    designates this particular file as subject to the
  108.20 -    "Classpath" exception as provided by apidesign.org
  108.21 -    in the License file that accompanied this code.
  108.22 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  108.23 +    Other names may be trademarks of their respective owners.
  108.24  
  108.25 -    You should have received a copy of the GNU General Public License
  108.26 -    along with this program. Look for COPYING file in the top folder.
  108.27 -    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  108.28 +    The contents of this file are subject to the terms of either the GNU
  108.29 +    General Public License Version 2 only ("GPL") or the Common
  108.30 +    Development and Distribution License("CDDL") (collectively, the
  108.31 +    "License"). You may not use this file except in compliance with the
  108.32 +    License. You can obtain a copy of the License at
  108.33 +    http://www.netbeans.org/cddl-gplv2.html
  108.34 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  108.35 +    specific language governing permissions and limitations under the
  108.36 +    License.  When distributing the software, include this License Header
  108.37 +    Notice in each file and include the License file at
  108.38 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  108.39 +    particular file as subject to the "Classpath" exception as provided
  108.40 +    by Oracle in the GPL Version 2 section of the License file that
  108.41 +    accompanied this code. If applicable, add the following below the
  108.42 +    License Header, with the fields enclosed by brackets [] replaced by
  108.43 +    your own identifying information:
  108.44 +    "Portions Copyrighted [year] [name of copyright owner]"
  108.45 +
  108.46 +    Contributor(s):
  108.47 +
  108.48 +    The Original Software is NetBeans. The Initial Developer of the Original
  108.49 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  108.50 +
  108.51 +    If you wish your version of this file to be governed by only the CDDL
  108.52 +    or only the GPL Version 2, indicate your decision by adding
  108.53 +    "[Contributor] elects to include this software in this distribution
  108.54 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
  108.55 +    single choice of license, a recipient has the option to distribute
  108.56 +    your version of this file under either the CDDL, the GPL Version 2 or
  108.57 +    to extend the choice of license to its licensees as provided above.
  108.58 +    However, if you add GPL Version 2 code and therefore, elected the GPL
  108.59 +    Version 2 license, then the option applies only if the new code is
  108.60 +    made subject to such option by the copyright holder.
  108.61  
  108.62  -->
  108.63  <body>
   109.1 --- a/json/src/main/java/org/apidesign/html/json/impl/Bindings.java	Mon Dec 16 17:16:02 2013 +0100
   109.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   109.3 @@ -1,91 +0,0 @@
   109.4 -/**
   109.5 - * HTML via Java(tm) Language Bindings
   109.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   109.7 - *
   109.8 - * This program is free software: you can redistribute it and/or modify
   109.9 - * it under the terms of the GNU General Public License as published by
  109.10 - * the Free Software Foundation, version 2 of the License.
  109.11 - *
  109.12 - * This program is distributed in the hope that it will be useful,
  109.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  109.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  109.15 - * GNU General Public License for more details. apidesign.org
  109.16 - * designates this particular file as subject to the
  109.17 - * "Classpath" exception as provided by apidesign.org
  109.18 - * in the License file that accompanied this code.
  109.19 - *
  109.20 - * You should have received a copy of the GNU General Public License
  109.21 - * along with this program. Look for COPYING file in the top folder.
  109.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  109.23 - */
  109.24 -package org.apidesign.html.json.impl;
  109.25 -
  109.26 -import org.apidesign.html.json.spi.PropertyBinding;
  109.27 -import net.java.html.BrwsrCtx;
  109.28 -import org.apidesign.html.json.impl.PropertyBindingAccessor.FBData;
  109.29 -import org.apidesign.html.json.impl.PropertyBindingAccessor.PBData;
  109.30 -import org.apidesign.html.json.spi.FunctionBinding;
  109.31 -import org.apidesign.html.json.spi.Technology;
  109.32 -
  109.33 -/**
  109.34 - *
  109.35 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  109.36 - */
  109.37 -public final class Bindings<Data> {
  109.38 -    private Data data;
  109.39 -    private final Technology<Data> bp;
  109.40 -
  109.41 -    private Bindings(Technology<Data> bp) {
  109.42 -        this.bp = bp;
  109.43 -    }
  109.44 -    
  109.45 -    public <M> PropertyBinding registerProperty(String propName, M model, SetAndGet<M> access, boolean readOnly) {
  109.46 -        return PropertyBindingAccessor.create(new PBData<M>(this, propName, model, access, readOnly));
  109.47 -    }
  109.48 -
  109.49 -    public <M> FunctionBinding registerFunction(String name, M model, Callback<M> access) {
  109.50 -        return PropertyBindingAccessor.createFunction(new FBData<M>(name, model, access));
  109.51 -    }
  109.52 -    
  109.53 -    public static Bindings<?> apply(BrwsrCtx c, Object model) {
  109.54 -        Technology<?> bp = JSON.findTechnology(c);
  109.55 -        return apply(bp);
  109.56 -    }
  109.57 -    
  109.58 -    private static <Data> Bindings<Data> apply(Technology<Data> bp) {
  109.59 -        return new Bindings<Data>(bp);
  109.60 -    }
  109.61 -    
  109.62 -    public final void finish(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
  109.63 -        assert data == null;
  109.64 -        if (bp instanceof Technology.BatchInit) {
  109.65 -            Technology.BatchInit<Data> bi = (Technology.BatchInit<Data>)bp;
  109.66 -            data = bi.wrapModel(model, propArr, funcArr);
  109.67 -        } else {
  109.68 -            data = bp.wrapModel(model);
  109.69 -            for (PropertyBinding b : propArr) {
  109.70 -                bp.bind(b, model, data);
  109.71 -            }
  109.72 -            for (FunctionBinding b : funcArr) {
  109.73 -                bp.expose(b, model, data);
  109.74 -            }
  109.75 -        }
  109.76 -    }
  109.77 -    
  109.78 -    
  109.79 -    public Data koData() {
  109.80 -        return data;
  109.81 -    }
  109.82 -
  109.83 -    public void valueHasMutated(String firstName) {
  109.84 -        bp.valueHasMutated(data, firstName);
  109.85 -    }
  109.86 -    
  109.87 -    public void applyBindings() {
  109.88 -        bp.applyBindings(data);
  109.89 -    }
  109.90 -
  109.91 -    Object wrapArray(Object[] arr) {
  109.92 -        return bp.wrapArray(arr);
  109.93 -    }
  109.94 -}
   110.1 --- a/json/src/main/java/org/apidesign/html/json/impl/Callback.java	Mon Dec 16 17:16:02 2013 +0100
   110.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   110.3 @@ -1,30 +0,0 @@
   110.4 -/**
   110.5 - * HTML via Java(tm) Language Bindings
   110.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   110.7 - *
   110.8 - * This program is free software: you can redistribute it and/or modify
   110.9 - * it under the terms of the GNU General Public License as published by
  110.10 - * the Free Software Foundation, version 2 of the License.
  110.11 - *
  110.12 - * This program is distributed in the hope that it will be useful,
  110.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  110.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  110.15 - * GNU General Public License for more details. apidesign.org
  110.16 - * designates this particular file as subject to the
  110.17 - * "Classpath" exception as provided by apidesign.org
  110.18 - * in the License file that accompanied this code.
  110.19 - *
  110.20 - * You should have received a copy of the GNU General Public License
  110.21 - * along with this program. Look for COPYING file in the top folder.
  110.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  110.23 - */
  110.24 -
  110.25 -package org.apidesign.html.json.impl;
  110.26 -
  110.27 -/**
  110.28 - *
  110.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  110.30 - */
  110.31 -public interface Callback<Data> {
  110.32 -    public void call(Data model, Object data, Object ev);
  110.33 -}
   111.1 --- a/json/src/main/java/org/apidesign/html/json/impl/FromJSON.java	Mon Dec 16 17:16:02 2013 +0100
   111.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   111.3 @@ -1,34 +0,0 @@
   111.4 -/**
   111.5 - * HTML via Java(tm) Language Bindings
   111.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   111.7 - *
   111.8 - * This program is free software: you can redistribute it and/or modify
   111.9 - * it under the terms of the GNU General Public License as published by
  111.10 - * the Free Software Foundation, version 2 of the License.
  111.11 - *
  111.12 - * This program is distributed in the hope that it will be useful,
  111.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  111.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  111.15 - * GNU General Public License for more details. apidesign.org
  111.16 - * designates this particular file as subject to the
  111.17 - * "Classpath" exception as provided by apidesign.org
  111.18 - * in the License file that accompanied this code.
  111.19 - *
  111.20 - * You should have received a copy of the GNU General Public License
  111.21 - * along with this program. Look for COPYING file in the top folder.
  111.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  111.23 - */
  111.24 -
  111.25 -package org.apidesign.html.json.impl;
  111.26 -
  111.27 -import net.java.html.BrwsrCtx;
  111.28 -
  111.29 -/**
  111.30 - *
  111.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  111.32 - */
  111.33 -public interface FromJSON<Data> {
  111.34 -    public Class<Data> factoryFor();
  111.35 -    public Data read(BrwsrCtx c, Object d);
  111.36 -    public Data cloneTo(Object d, BrwsrCtx c);
  111.37 -}
   112.1 --- a/json/src/main/java/org/apidesign/html/json/impl/JSON.java	Mon Dec 16 17:16:02 2013 +0100
   112.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   112.3 @@ -1,452 +0,0 @@
   112.4 -/**
   112.5 - * HTML via Java(tm) Language Bindings
   112.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   112.7 - *
   112.8 - * This program is free software: you can redistribute it and/or modify
   112.9 - * it under the terms of the GNU General Public License as published by
  112.10 - * the Free Software Foundation, version 2 of the License.
  112.11 - *
  112.12 - * This program is distributed in the hope that it will be useful,
  112.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  112.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  112.15 - * GNU General Public License for more details. apidesign.org
  112.16 - * designates this particular file as subject to the
  112.17 - * "Classpath" exception as provided by apidesign.org
  112.18 - * in the License file that accompanied this code.
  112.19 - *
  112.20 - * You should have received a copy of the GNU General Public License
  112.21 - * along with this program. Look for COPYING file in the top folder.
  112.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  112.23 - */
  112.24 -package org.apidesign.html.json.impl;
  112.25 -
  112.26 -import java.io.IOException;
  112.27 -import java.io.InputStream;
  112.28 -import java.util.HashMap;
  112.29 -import java.util.Map;
  112.30 -import net.java.html.BrwsrCtx;
  112.31 -import org.apidesign.html.context.spi.Contexts;
  112.32 -import org.apidesign.html.json.spi.FunctionBinding;
  112.33 -import org.apidesign.html.json.spi.JSONCall;
  112.34 -import org.apidesign.html.json.spi.PropertyBinding;
  112.35 -import org.apidesign.html.json.spi.Technology;
  112.36 -import org.apidesign.html.json.spi.Transfer;
  112.37 -import org.apidesign.html.json.spi.WSTransfer;
  112.38 -
  112.39 -/**
  112.40 - *
  112.41 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  112.42 - */
  112.43 -public final class JSON {
  112.44 -    private JSON() {
  112.45 -    }
  112.46 -
  112.47 -    static Technology<?> findTechnology(BrwsrCtx c) {
  112.48 -        Technology<?> t = Contexts.find(c, Technology.class);
  112.49 -        return t == null ? EmptyTech.EMPTY : t;
  112.50 -    }
  112.51 -
  112.52 -    static Transfer findTransfer(BrwsrCtx c) {
  112.53 -        Transfer t = Contexts.find(c, Transfer.class);
  112.54 -        return t == null ? EmptyTech.EMPTY : t;
  112.55 -    }
  112.56 -
  112.57 -    static WSTransfer<?> findWSTransfer(BrwsrCtx c) {
  112.58 -        WSTransfer<?> t = Contexts.find(c, WSTransfer.class);
  112.59 -        return t == null ? EmptyTech.EMPTY : t;
  112.60 -    }
  112.61 -    
  112.62 -    public static void runInBrowser(BrwsrCtx c, Runnable runnable) {
  112.63 -        findTechnology(c).runSafe(runnable);
  112.64 -    }
  112.65 -    
  112.66 -    public static void extract(BrwsrCtx c, Object value, String[] props, Object[] values) {
  112.67 -        Transfer t = findTransfer(c);
  112.68 -        t.extract(value, props, values);
  112.69 -    }
  112.70 -    
  112.71 -    private static Object getProperty(BrwsrCtx c, Object obj, String prop) {
  112.72 -        if (prop == null) return obj;
  112.73 -        
  112.74 -        String[] arr = { prop };
  112.75 -        Object[] val = { null };
  112.76 -        extract(c, obj, arr, val);
  112.77 -        return val[0];
  112.78 -    }
  112.79 -
  112.80 -    public static Object toJSON(Object value) {
  112.81 -        if (value == null) {
  112.82 -            return "null";
  112.83 -        }
  112.84 -        if (value instanceof Enum) {
  112.85 -            value = value.toString();
  112.86 -        }
  112.87 -        if (value instanceof String) {
  112.88 -            String s = (String)value;
  112.89 -            int len = s.length();
  112.90 -            StringBuilder sb = new StringBuilder(len + 10);
  112.91 -            sb.append('"');
  112.92 -            for (int i = 0; i < len; i++) {
  112.93 -                char ch = s.charAt(i);
  112.94 -                switch (ch) {
  112.95 -                    case '\"': sb.append("\\\""); break;
  112.96 -                    case '\n': sb.append("\\n"); break;
  112.97 -                    case '\r': sb.append("\\r"); break;
  112.98 -                    case '\t': sb.append("\\t"); break;
  112.99 -                    case '\\': sb.append("\\\\"); break;
 112.100 -                    default: sb.append(ch);
 112.101 -                }
 112.102 -            }
 112.103 -            sb.append('"');
 112.104 -            return sb.toString();
 112.105 -        }
 112.106 -        return value.toString();
 112.107 -    }
 112.108 -
 112.109 -    public static String toString(BrwsrCtx c, Object obj, String prop) {
 112.110 -        obj = getProperty(c, obj, prop);
 112.111 -        return obj instanceof String ? (String)obj : null;
 112.112 -    }
 112.113 -    public static Number toNumber(BrwsrCtx c, Object obj, String prop) {
 112.114 -        obj = getProperty(c, obj, prop);
 112.115 -        if (!(obj instanceof Number)) {
 112.116 -            obj = Double.NaN;
 112.117 -        }
 112.118 -        return (Number)obj;
 112.119 -    }
 112.120 -    public static <M> M toModel(BrwsrCtx c, Class<M> aClass, Object data, Object object) {
 112.121 -        Technology<?> t = findTechnology(c);
 112.122 -        Object o = t.toModel(aClass, data);
 112.123 -        return aClass.cast(o);
 112.124 -    }
 112.125 -    
 112.126 -    public static boolean isSame(int a, int b) {
 112.127 -        return a == b;
 112.128 -    }
 112.129 -    
 112.130 -    public static boolean isSame(double a, double b) {
 112.131 -        return a == b;
 112.132 -    }
 112.133 -    
 112.134 -    public static boolean isSame(Object a, Object b) {
 112.135 -        if (a == b) {
 112.136 -            return true;
 112.137 -        }
 112.138 -        if (a == null || b == null) {
 112.139 -            return false;
 112.140 -        }
 112.141 -        return a.equals(b);
 112.142 -    }
 112.143 -    
 112.144 -    public static int hashPlus(Object o, int h) {
 112.145 -        return o == null ? h : h ^ o.hashCode();
 112.146 -    }
 112.147 -
 112.148 -    public static <T> T extractValue(Class<T> type, Object val) {
 112.149 -        if (Number.class.isAssignableFrom(type)) {
 112.150 -            val = numberValue(val);
 112.151 -        }
 112.152 -        if (Boolean.class == type) {
 112.153 -            val = boolValue(val);
 112.154 -        }
 112.155 -        if (String.class == type) {
 112.156 -            val = stringValue(val);
 112.157 -        }
 112.158 -        if (Character.class == type) {
 112.159 -            val = charValue(val);
 112.160 -        }
 112.161 -        if (Integer.class == type) {
 112.162 -            val = val instanceof Number ? ((Number)val).intValue() : 0;
 112.163 -        }
 112.164 -        if (Long.class == type) {
 112.165 -            val = val instanceof Number  ? ((Number)val).longValue() : 0;
 112.166 -        }
 112.167 -        if (Short.class == type) {
 112.168 -            val = val instanceof Number ? ((Number)val).shortValue() : 0;
 112.169 -        }
 112.170 -        if (Byte.class == type) {
 112.171 -            val = val instanceof Number ? ((Number)val).byteValue() : 0;
 112.172 -        }        
 112.173 -        if (Double.class == type) {
 112.174 -            val = val instanceof Number ? ((Number)val).doubleValue() : Double.NaN;
 112.175 -        }
 112.176 -        if (Float.class == type) {
 112.177 -            val = val instanceof Number ? ((Number)val).floatValue() : Float.NaN;
 112.178 -        }
 112.179 -        return type.cast(val);
 112.180 -    }
 112.181 -    
 112.182 -    protected static boolean isNumeric(Object val) {
 112.183 -        return ((val instanceof Integer) || (val instanceof Long) || (val instanceof Short) || (val instanceof Byte));
 112.184 -    }
 112.185 -    
 112.186 -    public static String stringValue(Object val) {
 112.187 -        if (val instanceof Boolean) {
 112.188 -            return ((Boolean)val ? "true" : "false");
 112.189 -        }
 112.190 -        if (isNumeric(val)) {
 112.191 -            return Long.toString(((Number)val).longValue());
 112.192 -        }
 112.193 -        if (val instanceof Float) {
 112.194 -            return Float.toString((Float)val);
 112.195 -        }
 112.196 -        if (val instanceof Double) {
 112.197 -            return Double.toString((Double)val);
 112.198 -        }
 112.199 -        return (String)val;
 112.200 -    }
 112.201 -
 112.202 -    public static Number numberValue(Object val) {
 112.203 -        if (val instanceof String) {
 112.204 -            try {
 112.205 -                return Double.valueOf((String)val);
 112.206 -            } catch (NumberFormatException ex) {
 112.207 -                return Double.NaN;
 112.208 -            }
 112.209 -        }
 112.210 -        if (val instanceof Boolean) {
 112.211 -            return (Boolean)val ? 1 : 0;
 112.212 -        }
 112.213 -        return (Number)val;
 112.214 -    }
 112.215 -
 112.216 -    public static Character charValue(Object val) {
 112.217 -        if (val instanceof Number) {
 112.218 -            return Character.toChars(numberValue(val).intValue())[0];
 112.219 -        }
 112.220 -        if (val instanceof Boolean) {
 112.221 -            return (Boolean)val ? (char)1 : (char)0;
 112.222 -        }
 112.223 -        if (val instanceof String) {
 112.224 -            String s = (String)val;
 112.225 -            return s.isEmpty() ? (char)0 : s.charAt(0);
 112.226 -        }
 112.227 -        return (Character)val;
 112.228 -    }
 112.229 -    
 112.230 -    public static Boolean boolValue(Object val) {
 112.231 -        if (val instanceof String) {
 112.232 -            return Boolean.parseBoolean((String)val);
 112.233 -        }
 112.234 -        if (val instanceof Number) {
 112.235 -            return numberValue(val).doubleValue() != 0.0;
 112.236 -        }
 112.237 -    
 112.238 -        return Boolean.TRUE.equals(val);
 112.239 -    }
 112.240 -    
 112.241 -    public static void loadJSON(
 112.242 -        BrwsrCtx c, RcvrJSON callback,
 112.243 -        String urlBefore, String urlAfter, String method,
 112.244 -        Object data
 112.245 -    ) {
 112.246 -        JSONCall call = PropertyBindingAccessor.createCall(c, callback, urlBefore, urlAfter, method, data);
 112.247 -        Transfer t = findTransfer(c);
 112.248 -        t.loadJSON(call);
 112.249 -    }
 112.250 -    public static WS openWS(
 112.251 -        BrwsrCtx c, RcvrJSON r, String url, Object data
 112.252 -    ) {
 112.253 -        WS ws = WSImpl.create(findWSTransfer(c), r);
 112.254 -        ws.send(c, url, data);
 112.255 -        return ws;
 112.256 -    }
 112.257 -    
 112.258 -    public static abstract class WS {
 112.259 -        private WS() {
 112.260 -        }
 112.261 -        
 112.262 -        public abstract void send(BrwsrCtx ctx, String url, Object model);
 112.263 -    }
 112.264 -    
 112.265 -    private static final class WSImpl<Socket> extends WS {
 112.266 -
 112.267 -        private final WSTransfer<Socket> trans;
 112.268 -        private final RcvrJSON rcvr;
 112.269 -        private Socket socket;
 112.270 -        private String prevURL;
 112.271 -
 112.272 -        private WSImpl(WSTransfer<Socket> trans, RcvrJSON rcvr) {
 112.273 -            this.trans = trans;
 112.274 -            this.rcvr = rcvr;
 112.275 -        }
 112.276 -        
 112.277 -        static <Socket> WS create(WSTransfer<Socket> t, RcvrJSON r) {
 112.278 -            return new WSImpl<Socket>(t, r);
 112.279 -        }
 112.280 -
 112.281 -        @Override
 112.282 -        public void send(BrwsrCtx ctx, String url, Object data) {
 112.283 -            Socket s = socket;
 112.284 -            if (s == null) {
 112.285 -                if (data != null) {
 112.286 -                    throw new IllegalStateException("WebSocket is not opened yet. Call with null data, was: " + data);
 112.287 -                }
 112.288 -                JSONCall call = PropertyBindingAccessor.createCall(ctx, rcvr, url, null, "WebSocket", null);
 112.289 -                socket = trans.open(url, call);
 112.290 -                prevURL = url;
 112.291 -                return;
 112.292 -            }
 112.293 -            if (data == null) {
 112.294 -                trans.close(s);
 112.295 -                socket = null;
 112.296 -                return;
 112.297 -            }
 112.298 -            if (!prevURL.equals(url)) {
 112.299 -                throw new IllegalStateException(
 112.300 -                    "Can't call to different URL " + url + " was: " + prevURL + "!"
 112.301 -                    + " Close the socket by calling it will null data first!"
 112.302 -                );
 112.303 -            }
 112.304 -            JSONCall call = PropertyBindingAccessor.createCall(ctx, rcvr, prevURL, null, "WebSocket", data);
 112.305 -            trans.send(s, call);
 112.306 -        }
 112.307 -        
 112.308 -    }
 112.309 -    
 112.310 -    private static final Map<Class,FromJSON<?>> froms;
 112.311 -    static {
 112.312 -        Map<Class,FromJSON<?>> m = new HashMap<Class,FromJSON<?>>();
 112.313 -        froms = m;
 112.314 -    }
 112.315 -    public static void register(FromJSON<?> from) {
 112.316 -        froms.put(from.factoryFor(), from);
 112.317 -    }
 112.318 -    
 112.319 -    public static boolean isModel(Class<?> clazz) {
 112.320 -        return findFrom(clazz) != null; 
 112.321 -    }
 112.322 -    
 112.323 -    private static FromJSON<?> findFrom(Class<?> clazz) {
 112.324 -        for (int i = 0; i < 2; i++) {
 112.325 -            FromJSON<?> from = froms.get(clazz);
 112.326 -            if (from == null) {
 112.327 -                initClass(clazz);
 112.328 -            } else {
 112.329 -                return from;
 112.330 -            }
 112.331 -        }
 112.332 -        return null;
 112.333 -    }
 112.334 -    
 112.335 -    public static <Model> Model bindTo(Model model, BrwsrCtx c) {
 112.336 -        FromJSON<?> from = findFrom(model.getClass());
 112.337 -        if (from == null) {
 112.338 -            throw new IllegalArgumentException();
 112.339 -        }
 112.340 -        return (Model) from.cloneTo(model, c);
 112.341 -    }
 112.342 -    
 112.343 -    public static <T> T readStream(BrwsrCtx c, Class<T> modelClazz, InputStream data) 
 112.344 -    throws IOException {
 112.345 -        Transfer tr = findTransfer(c);
 112.346 -        return read(c, modelClazz, tr.toJSON((InputStream)data));
 112.347 -    }
 112.348 -    public static <T> T read(BrwsrCtx c, Class<T> modelClazz, Object data) {
 112.349 -        if (data == null) {
 112.350 -            return null;
 112.351 -        }
 112.352 -        if (modelClazz == String.class) {
 112.353 -            return modelClazz.cast(data.toString());
 112.354 -        }
 112.355 -        for (int i = 0; i < 2; i++) {
 112.356 -            FromJSON<?> from = froms.get(modelClazz);
 112.357 -            if (from == null) {
 112.358 -                initClass(modelClazz);
 112.359 -            } else {
 112.360 -                return modelClazz.cast(from.read(c, data));
 112.361 -            }
 112.362 -        }
 112.363 -        throw new NullPointerException();
 112.364 -    }
 112.365 -    static void initClass(Class<?> modelClazz) {
 112.366 -        try {
 112.367 -            // try to resolve the class
 112.368 -            ClassLoader l;
 112.369 -            try {
 112.370 -                l = modelClazz.getClassLoader();
 112.371 -            } catch (SecurityException ex) {
 112.372 -                l = null;
 112.373 -            }
 112.374 -            if (l != null) {
 112.375 -                Class.forName(modelClazz.getName(), true, l);
 112.376 -            }
 112.377 -            modelClazz.newInstance();
 112.378 -        } catch (Exception ex) {
 112.379 -            // ignore and try again
 112.380 -        }
 112.381 -    }
 112.382 -    
 112.383 -    private static final class EmptyTech
 112.384 -    implements Technology<Object>, Transfer, WSTransfer<Void> {
 112.385 -        private static final EmptyTech EMPTY = new EmptyTech();
 112.386 -
 112.387 -        @Override
 112.388 -        public Object wrapModel(Object model) {
 112.389 -            return model;
 112.390 -        }
 112.391 -
 112.392 -        @Override
 112.393 -        public void valueHasMutated(Object data, String propertyName) {
 112.394 -        }
 112.395 -
 112.396 -        @Override
 112.397 -        public void bind(PropertyBinding b, Object model, Object data) {
 112.398 -        }
 112.399 -
 112.400 -        @Override
 112.401 -        public void expose(FunctionBinding fb, Object model, Object d) {
 112.402 -        }
 112.403 -
 112.404 -        @Override
 112.405 -        public void applyBindings(Object data) {
 112.406 -        }
 112.407 -
 112.408 -        @Override
 112.409 -        public Object wrapArray(Object[] arr) {
 112.410 -            return arr;
 112.411 -        }
 112.412 -
 112.413 -        @Override
 112.414 -        public void extract(Object obj, String[] props, Object[] values) {
 112.415 -            for (int i = 0; i < values.length; i++) {
 112.416 -                values[i] = null;
 112.417 -            }
 112.418 -        }
 112.419 -
 112.420 -        @Override
 112.421 -        public void loadJSON(JSONCall call) {
 112.422 -            call.notifyError(new UnsupportedOperationException());
 112.423 -        }
 112.424 -
 112.425 -        @Override
 112.426 -        public <M> M toModel(Class<M> modelClass, Object data) {
 112.427 -            return modelClass.cast(data);
 112.428 -        }
 112.429 -
 112.430 -        @Override
 112.431 -        public Object toJSON(InputStream is) throws IOException {
 112.432 -            throw new IOException("Not supported");
 112.433 -        }
 112.434 -
 112.435 -        @Override
 112.436 -        public synchronized void runSafe(Runnable r) {
 112.437 -            r.run();
 112.438 -        }
 112.439 -
 112.440 -        @Override
 112.441 -        public Void open(String url, JSONCall onReply) {
 112.442 -            onReply.notifyError(new UnsupportedOperationException("WebSockets not supported!"));
 112.443 -            return null;
 112.444 -        }
 112.445 -
 112.446 -        @Override
 112.447 -        public void send(Void socket, JSONCall data) {
 112.448 -        }
 112.449 -
 112.450 -        @Override
 112.451 -        public void close(Void socket) {
 112.452 -        }
 112.453 -    }
 112.454 -    
 112.455 -}
   113.1 --- a/json/src/main/java/org/apidesign/html/json/impl/JSONList.java	Mon Dec 16 17:16:02 2013 +0100
   113.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   113.3 @@ -1,214 +0,0 @@
   113.4 -/**
   113.5 - * HTML via Java(tm) Language Bindings
   113.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   113.7 - *
   113.8 - * This program is free software: you can redistribute it and/or modify
   113.9 - * it under the terms of the GNU General Public License as published by
  113.10 - * the Free Software Foundation, version 2 of the License.
  113.11 - *
  113.12 - * This program is distributed in the hope that it will be useful,
  113.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  113.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  113.15 - * GNU General Public License for more details. apidesign.org
  113.16 - * designates this particular file as subject to the
  113.17 - * "Classpath" exception as provided by apidesign.org
  113.18 - * in the License file that accompanied this code.
  113.19 - *
  113.20 - * You should have received a copy of the GNU General Public License
  113.21 - * along with this program. Look for COPYING file in the top folder.
  113.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  113.23 - */
  113.24 -package org.apidesign.html.json.impl;
  113.25 -
  113.26 -import java.lang.reflect.Array;
  113.27 -import java.util.ArrayList;
  113.28 -import java.util.Arrays;
  113.29 -import java.util.Collection;
  113.30 -import java.util.Iterator;
  113.31 -import java.util.List;
  113.32 -import net.java.html.BrwsrCtx;
  113.33 -
  113.34 -/**
  113.35 - *
  113.36 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  113.37 - */
  113.38 -public final class JSONList<T> extends ArrayList<T> {
  113.39 -    private final String name;
  113.40 -    private final String[] deps;
  113.41 -    private Bindings[] model;
  113.42 -    private Runnable onchange;
  113.43 -
  113.44 -    public JSONList(Bindings[] model, String name, String... deps) {
  113.45 -        assert model.length == 1;
  113.46 -        this.model = model;
  113.47 -        this.name = name;
  113.48 -        this.deps = deps;
  113.49 -    }
  113.50 -    
  113.51 -    public void init(T... values) {
  113.52 -        if (values == null || values.length == 0) {
  113.53 -            return;
  113.54 -        }
  113.55 -        if (this.model[0] != null || !isEmpty()) {
  113.56 -            throw new IllegalStateException();
  113.57 -        }
  113.58 -        super.addAll(Arrays.asList(values));
  113.59 -    }
  113.60 -    
  113.61 -    public void init(Object values) {
  113.62 -        int len;
  113.63 -        if (values == null || (len = Array.getLength(values)) == 0) {
  113.64 -            return;
  113.65 -        }
  113.66 -        if (this.model[0] != null || !isEmpty()) {
  113.67 -            throw new IllegalStateException();
  113.68 -        }
  113.69 -        for (int i = 0; i < len; i++) {
  113.70 -            Object data = Array.get(values, i);
  113.71 -            super.add((T)data);
  113.72 -        }
  113.73 -    }
  113.74 -    
  113.75 -    public JSONList<T> onChange(Runnable r) {
  113.76 -        if (this.onchange != null) {
  113.77 -            throw new IllegalStateException();
  113.78 -        }
  113.79 -        this.onchange = r;
  113.80 -        return this;
  113.81 -    }
  113.82 -
  113.83 -    @Override
  113.84 -    public boolean add(T e) {
  113.85 -        boolean ret = super.add(e);
  113.86 -        notifyChange();
  113.87 -        return ret;
  113.88 -    }
  113.89 -
  113.90 -    @Override
  113.91 -    public boolean addAll(Collection<? extends T> c) {
  113.92 -        boolean ret = super.addAll(c);
  113.93 -        notifyChange();
  113.94 -        return ret;
  113.95 -    }
  113.96 -
  113.97 -    @Override
  113.98 -    public boolean addAll(int index, Collection<? extends T> c) {
  113.99 -        boolean ret = super.addAll(index, c);
 113.100 -        notifyChange();
 113.101 -        return ret;
 113.102 -    }
 113.103 -
 113.104 -    @Override
 113.105 -    public boolean remove(Object o) {
 113.106 -        boolean ret = super.remove(o);
 113.107 -        notifyChange();
 113.108 -        return ret;
 113.109 -    }
 113.110 -
 113.111 -    @Override
 113.112 -    public void clear() {
 113.113 -        super.clear();
 113.114 -        notifyChange();
 113.115 -    }
 113.116 -
 113.117 -    @Override
 113.118 -    public boolean removeAll(Collection<?> c) {
 113.119 -        boolean ret = super.removeAll(c);
 113.120 -        notifyChange();
 113.121 -        return ret;
 113.122 -    }
 113.123 -
 113.124 -    @Override
 113.125 -    public boolean retainAll(Collection<?> c) {
 113.126 -        boolean ret = super.retainAll(c);
 113.127 -        notifyChange();
 113.128 -        return ret;
 113.129 -    }
 113.130 -
 113.131 -    @Override
 113.132 -    public T set(int index, T element) {
 113.133 -        T ret = super.set(index, element);
 113.134 -        notifyChange();
 113.135 -        return ret;
 113.136 -    }
 113.137 -
 113.138 -    @Override
 113.139 -    public void add(int index, T element) {
 113.140 -        super.add(index, element);
 113.141 -        notifyChange();
 113.142 -    }
 113.143 -
 113.144 -    @Override
 113.145 -    public T remove(int index) {
 113.146 -        T ret = super.remove(index);
 113.147 -        notifyChange();
 113.148 -        return ret;
 113.149 -    }
 113.150 -
 113.151 -    @Override
 113.152 -    public String toString() {
 113.153 -        Iterator<T> it = iterator();
 113.154 -        if (!it.hasNext()) {
 113.155 -            return "[]";
 113.156 -        }
 113.157 -        String sep = "";
 113.158 -        StringBuilder sb = new StringBuilder();
 113.159 -        sb.append('[');
 113.160 -        while (it.hasNext()) {
 113.161 -            T t = it.next();
 113.162 -            sb.append(sep);
 113.163 -            sb.append(JSON.toJSON(t));
 113.164 -            sep = ",";
 113.165 -        }
 113.166 -        sb.append(']');
 113.167 -        return sb.toString();
 113.168 -    }
 113.169 -
 113.170 -    private void notifyChange() {
 113.171 -        Bindings m = model[0];
 113.172 -        if (m != null) {
 113.173 -            m.valueHasMutated(name);
 113.174 -            for (String dependant : deps) {
 113.175 -                m.valueHasMutated(dependant);
 113.176 -            }
 113.177 -            Runnable r = onchange;
 113.178 -            if (r != null) {
 113.179 -                r.run();
 113.180 -            }
 113.181 -        }
 113.182 -    }
 113.183 -    
 113.184 -    public void cloneAll(BrwsrCtx c, Collection<T> other) {
 113.185 -        Boolean isModel = null;
 113.186 -        for (T t : other) {
 113.187 -            if (isModel == null) {
 113.188 -                isModel = JSON.isModel(t.getClass());
 113.189 -            }
 113.190 -            if (isModel) {
 113.191 -                add(JSON.bindTo(t, c));
 113.192 -            } else {
 113.193 -                add(t);
 113.194 -            }
 113.195 -        }
 113.196 -    }
 113.197 -
 113.198 -    @Override
 113.199 -    public JSONList clone() {
 113.200 -        throw new UnsupportedOperationException();
 113.201 -    }
 113.202 -
 113.203 -    static final Object koData(Collection<?> c, Bindings m) {
 113.204 -        Object[] arr = c.toArray(new Object[c.size()]);
 113.205 -        for (int i = 0; i < arr.length; i++) {
 113.206 -            Object r = WrapperObject.find(arr[i], m);
 113.207 -            if (r != null) {
 113.208 -                arr[i] = r;
 113.209 -            }
 113.210 -        }
 113.211 -        return m.wrapArray(arr);
 113.212 -    }
 113.213 -
 113.214 -    final Object koData() {
 113.215 -        return koData(this, model[0]);
 113.216 -    }
 113.217 -}
   114.1 --- a/json/src/main/java/org/apidesign/html/json/impl/ModelProcessor.java	Mon Dec 16 17:16:02 2013 +0100
   114.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   114.3 @@ -1,1745 +0,0 @@
   114.4 -/**
   114.5 - * HTML via Java(tm) Language Bindings
   114.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   114.7 - *
   114.8 - * This program is free software: you can redistribute it and/or modify
   114.9 - * it under the terms of the GNU General Public License as published by
  114.10 - * the Free Software Foundation, version 2 of the License.
  114.11 - *
  114.12 - * This program is distributed in the hope that it will be useful,
  114.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  114.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  114.15 - * GNU General Public License for more details. apidesign.org
  114.16 - * designates this particular file as subject to the
  114.17 - * "Classpath" exception as provided by apidesign.org
  114.18 - * in the License file that accompanied this code.
  114.19 - *
  114.20 - * You should have received a copy of the GNU General Public License
  114.21 - * along with this program. Look for COPYING file in the top folder.
  114.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  114.23 - */
  114.24 -package org.apidesign.html.json.impl;
  114.25 -
  114.26 -import java.io.IOException;
  114.27 -import java.io.OutputStreamWriter;
  114.28 -import java.io.StringWriter;
  114.29 -import java.io.Writer;
  114.30 -import java.lang.annotation.AnnotationTypeMismatchException;
  114.31 -import java.lang.annotation.IncompleteAnnotationException;
  114.32 -import java.lang.reflect.Method;
  114.33 -import java.util.ArrayList;
  114.34 -import java.util.Arrays;
  114.35 -import java.util.Collection;
  114.36 -import java.util.Collections;
  114.37 -import java.util.HashMap;
  114.38 -import java.util.HashSet;
  114.39 -import java.util.LinkedHashSet;
  114.40 -import java.util.List;
  114.41 -import java.util.Map;
  114.42 -import java.util.ResourceBundle;
  114.43 -import java.util.Set;
  114.44 -import java.util.WeakHashMap;
  114.45 -import java.util.logging.Level;
  114.46 -import java.util.logging.Logger;
  114.47 -import javax.annotation.processing.AbstractProcessor;
  114.48 -import javax.annotation.processing.Completion;
  114.49 -import javax.annotation.processing.Completions;
  114.50 -import javax.annotation.processing.ProcessingEnvironment;
  114.51 -import javax.annotation.processing.Processor;
  114.52 -import javax.annotation.processing.RoundEnvironment;
  114.53 -import javax.annotation.processing.SupportedAnnotationTypes;
  114.54 -import javax.annotation.processing.SupportedSourceVersion;
  114.55 -import javax.lang.model.SourceVersion;
  114.56 -import javax.lang.model.element.AnnotationMirror;
  114.57 -import javax.lang.model.element.AnnotationValue;
  114.58 -import javax.lang.model.element.Element;
  114.59 -import javax.lang.model.element.ElementKind;
  114.60 -import javax.lang.model.element.ExecutableElement;
  114.61 -import javax.lang.model.element.Modifier;
  114.62 -import javax.lang.model.element.PackageElement;
  114.63 -import javax.lang.model.element.TypeElement;
  114.64 -import javax.lang.model.element.VariableElement;
  114.65 -import javax.lang.model.type.ArrayType;
  114.66 -import javax.lang.model.type.DeclaredType;
  114.67 -import javax.lang.model.type.MirroredTypeException;
  114.68 -import javax.lang.model.type.TypeKind;
  114.69 -import javax.lang.model.type.TypeMirror;
  114.70 -import javax.lang.model.util.Elements;
  114.71 -import javax.lang.model.util.Types;
  114.72 -import javax.tools.Diagnostic;
  114.73 -import javax.tools.FileObject;
  114.74 -import net.java.html.json.ComputedProperty;
  114.75 -import net.java.html.json.Model;
  114.76 -import net.java.html.json.Function;
  114.77 -import net.java.html.json.ModelOperation;
  114.78 -import net.java.html.json.OnPropertyChange;
  114.79 -import net.java.html.json.OnReceive;
  114.80 -import net.java.html.json.Property;
  114.81 -import org.openide.util.lookup.ServiceProvider;
  114.82 -
  114.83 -/** Annotation processor to process {@link Model @Model} annotations and
  114.84 - * generate appropriate model classes.
  114.85 - *
  114.86 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  114.87 - */
  114.88 -@ServiceProvider(service=Processor.class)
  114.89 -@SupportedSourceVersion(SourceVersion.RELEASE_6)
  114.90 -@SupportedAnnotationTypes({
  114.91 -    "net.java.html.json.Model",
  114.92 -    "net.java.html.json.ModelOperation",
  114.93 -    "net.java.html.json.Function",
  114.94 -    "net.java.html.json.OnReceive",
  114.95 -    "net.java.html.json.OnPropertyChange",
  114.96 -    "net.java.html.json.ComputedProperty",
  114.97 -    "net.java.html.json.Property"
  114.98 -})
  114.99 -public final class ModelProcessor extends AbstractProcessor {
 114.100 -    private static final Logger LOG = Logger.getLogger(ModelProcessor.class.getName());
 114.101 -    private final Map<Element,String> models = new WeakHashMap<Element,String>();
 114.102 -    private final Map<Element,Prprt[]> verify = new WeakHashMap<Element,Prprt[]>();
 114.103 -    @Override
 114.104 -    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
 114.105 -        boolean ok = true;
 114.106 -        for (Element e : roundEnv.getElementsAnnotatedWith(Model.class)) {
 114.107 -            if (!processModel(e)) {
 114.108 -                ok = false;
 114.109 -            }
 114.110 -        }
 114.111 -        if (roundEnv.processingOver()) {
 114.112 -            models.clear();
 114.113 -            for (Map.Entry<Element, Prprt[]> entry : verify.entrySet()) {
 114.114 -                TypeElement te = (TypeElement)entry.getKey();
 114.115 -                String fqn = processingEnv.getElementUtils().getBinaryName(te).toString();
 114.116 -                Element finalElem = processingEnv.getElementUtils().getTypeElement(fqn);
 114.117 -                if (finalElem == null) {
 114.118 -                    continue;
 114.119 -                }
 114.120 -                Prprt[] props;
 114.121 -                Model m = finalElem.getAnnotation(Model.class);
 114.122 -                if (m == null) {
 114.123 -                    continue;
 114.124 -                }
 114.125 -                props = Prprt.wrap(processingEnv, finalElem, m.properties());
 114.126 -                for (Prprt p : props) {
 114.127 -                    boolean[] isModel = { false };
 114.128 -                    boolean[] isEnum = { false };
 114.129 -                    boolean[] isPrimitive = { false };
 114.130 -                    String t = checkType(p, isModel, isEnum, isPrimitive);
 114.131 -                    if (isEnum[0]) {
 114.132 -                        continue;
 114.133 -                    }
 114.134 -                    if (isPrimitive[0]) {
 114.135 -                        continue;
 114.136 -                    }
 114.137 -                    if (isModel[0]) {
 114.138 -                        continue;
 114.139 -                    }
 114.140 -                    if ("java.lang.String".equals(t)) {
 114.141 -                        continue;
 114.142 -                    }
 114.143 -                    error("The type " + t + " should be defined by @Model annotation", entry.getKey());
 114.144 -                }
 114.145 -            }
 114.146 -            verify.clear();
 114.147 -        }
 114.148 -        return ok;
 114.149 -    }
 114.150 -
 114.151 -    private void error(String msg, Element e) {
 114.152 -        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e);
 114.153 -    }
 114.154 -    
 114.155 -    private boolean processModel(Element e) {
 114.156 -        boolean ok = true;
 114.157 -        Model m = e.getAnnotation(Model.class);
 114.158 -        if (m == null) {
 114.159 -            return true;
 114.160 -        }
 114.161 -        String pkg = findPkgName(e);
 114.162 -        Writer w;
 114.163 -        String className = m.className();
 114.164 -        models.put(e, className);
 114.165 -        try {
 114.166 -            StringWriter body = new StringWriter();
 114.167 -            List<String> propsGetSet = new ArrayList<String>();
 114.168 -            List<String> functions = new ArrayList<String>();
 114.169 -            Map<String, Collection<String>> propsDeps = new HashMap<String, Collection<String>>();
 114.170 -            Map<String, Collection<String>> functionDeps = new HashMap<String, Collection<String>>();
 114.171 -            Prprt[] props = createProps(e, m.properties());
 114.172 -            
 114.173 -            if (!generateComputedProperties(body, props, e.getEnclosedElements(), propsGetSet, propsDeps)) {
 114.174 -                ok = false;
 114.175 -            }
 114.176 -            if (!generateOnChange(e, propsDeps, props, className, functionDeps)) {
 114.177 -                ok = false;
 114.178 -            }
 114.179 -            if (!generateProperties(e, body, props, propsGetSet, propsDeps, functionDeps)) {
 114.180 -                ok = false;
 114.181 -            }
 114.182 -            if (!generateFunctions(e, body, className, e.getEnclosedElements(), functions)) {
 114.183 -                ok = false;
 114.184 -            }
 114.185 -            if (!generateReceive(e, body, className, e.getEnclosedElements(), functions)) {
 114.186 -                ok = false;
 114.187 -            }
 114.188 -            if (!generateOperation(e, body, className, e.getEnclosedElements())) {
 114.189 -                ok = false;
 114.190 -            }
 114.191 -            FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
 114.192 -            w = new OutputStreamWriter(java.openOutputStream());
 114.193 -            try {
 114.194 -                w.append("package " + pkg + ";\n");
 114.195 -                w.append("import net.java.html.json.*;\n");
 114.196 -                w.append("public final class ").append(className).append(" implements Cloneable {\n");
 114.197 -                w.append("  private boolean locked;\n");
 114.198 -                w.append("  private net.java.html.BrwsrCtx context;\n");
 114.199 -                w.append("  private org.apidesign.html.json.impl.Bindings[] ko = { null };\n");
 114.200 -                w.append(body.toString());
 114.201 -                w.append("  private static Class<" + inPckName(e) + "> modelFor() { return null; }\n");
 114.202 -                w.append("  private ").append(className).append("(net.java.html.BrwsrCtx context) {\n");
 114.203 -                w.append("    this.context = context;\n");
 114.204 -                w.append("  };\n");
 114.205 -                w.append("  public ").append(className).append("() {\n");
 114.206 -                w.append("    this(net.java.html.BrwsrCtx.findDefault(").append(className).append(".class));\n");
 114.207 -                for (Prprt p : props) {
 114.208 -                    if (p.array()) {
 114.209 -                        continue;
 114.210 -                    }
 114.211 -                    boolean[] isModel = {false};
 114.212 -                    boolean[] isEnum = {false};
 114.213 -                    boolean isPrimitive[] = {false};
 114.214 -                    String tn = checkType(p, isModel, isEnum, isPrimitive);
 114.215 -                    if (isModel[0]) {
 114.216 -                        w.write("    prop_" + p.name() + " = new " + tn + "();\n");
 114.217 -                    }
 114.218 -                }
 114.219 -                w.append("  };\n");
 114.220 -                if (props.length > 0) {
 114.221 -                    w.append("  public ").append(className).append("(");
 114.222 -                    Prprt firstArray = null;
 114.223 -                    String sep = "";
 114.224 -                    for (Prprt p : props) {
 114.225 -                        if (p.array()) {
 114.226 -                            if (firstArray == null) {
 114.227 -                                firstArray = p;
 114.228 -                            }
 114.229 -                            continue;
 114.230 -                        }
 114.231 -                        String tn = typeName(e, p);
 114.232 -                        w.write(sep);
 114.233 -                        w.write(tn);
 114.234 -                        w.write(" " + p.name());
 114.235 -                        sep = ", ";
 114.236 -                    }
 114.237 -                    if (firstArray != null) {
 114.238 -                        String tn;
 114.239 -                        boolean[] isModel = {false};
 114.240 -                        boolean[] isEnum = {false};
 114.241 -                        boolean isPrimitive[] = {false};
 114.242 -                        tn = checkType(firstArray, isModel, isEnum, isPrimitive);
 114.243 -                        w.write(sep);
 114.244 -                        w.write(tn);
 114.245 -                        w.write("... " + firstArray.name());
 114.246 -                    }
 114.247 -                    w.append(") {\n");
 114.248 -                    w.append("    this(net.java.html.BrwsrCtx.findDefault(").append(className).append(".class));\n");
 114.249 -                    for (Prprt p : props) {
 114.250 -                        if (p.array()) {
 114.251 -                            continue;
 114.252 -                        }
 114.253 -                        w.write("    this.prop_" + p.name() + " = " + p.name() + ";\n");
 114.254 -                    }
 114.255 -                    if (firstArray != null) {
 114.256 -                        w.write("    this.prop_" + firstArray.name() + ".init(" + firstArray.name() + ");\n");
 114.257 -                    }
 114.258 -                    w.append("  };\n");
 114.259 -                }
 114.260 -                w.append("  private org.apidesign.html.json.impl.Bindings intKnckt() {\n");
 114.261 -                w.append("    if (ko[0] != null) return ko[0];\n");
 114.262 -                w.append("    ko[0] = org.apidesign.html.json.impl.Bindings.apply(context, this);\n");
 114.263 -                {
 114.264 -                    w.append("    org.apidesign.html.json.spi.PropertyBinding[] propArr = {\n");
 114.265 -                    for (int i = 0; i < propsGetSet.size(); i += 5) {
 114.266 -                        w.append("      ko[0].registerProperty(\"").append(propsGetSet.get(i)).append("\", this, new P(");
 114.267 -                        w.append((i / 5) + "), " + (propsGetSet.get(i + 2) == null) + "),\n");
 114.268 -                    }
 114.269 -                    w.append("    };\n");
 114.270 -                }
 114.271 -                {
 114.272 -                    w.append("    org.apidesign.html.json.spi.FunctionBinding[] funcArr = {\n");
 114.273 -                    for (int i = 0; i < functions.size(); i += 2) {
 114.274 -                        w.append("      ko[0].registerFunction(\"").append(functions.get(i)).append("\", this, new P(");
 114.275 -                        w.append((i / 2) + ")),\n");
 114.276 -                    }
 114.277 -                    w.append("    };\n");
 114.278 -                }
 114.279 -                w.append("    ko[0].finish(this, propArr, funcArr);\n");
 114.280 -                w.append("    return ko[0];\n");
 114.281 -                w.append("  };\n");
 114.282 -                w.append("  private static final class P implements org.apidesign.html.json.impl.SetAndGet<" + className + ">,\n");
 114.283 -                w.append("  org.apidesign.html.json.impl.Callback<" + className + ">,\n");
 114.284 -                w.append("  org.apidesign.html.json.impl.FromJSON<" + className + "> {\n");
 114.285 -                w.append("    private final int type;\n");
 114.286 -                w.append("    P(int t) { type = t; };\n");
 114.287 -                w.append("    public void setValue(" + className + " data, Object value) {\n");
 114.288 -                w.append("      switch (type) {\n");
 114.289 -                for (int i = 0; i < propsGetSet.size(); i += 5) {
 114.290 -                    final String set = propsGetSet.get(i + 2);
 114.291 -                    String tn = propsGetSet.get(i + 4);
 114.292 -                    String btn = findBoxedType(tn);
 114.293 -                    if (btn != null) {
 114.294 -                        tn = btn;
 114.295 -                    }
 114.296 -                    if (set != null) {
 114.297 -                        w.append("        case " + (i / 5) + ": data." + strip(set) + "(org.apidesign.html.json.impl.JSON.extractValue(" + tn + ".class, value)); return;\n");
 114.298 -                    }
 114.299 -                }
 114.300 -                w.append("      }\n");
 114.301 -                w.append("    }\n");
 114.302 -                w.append("    public Object getValue(" + className + " data) {\n");
 114.303 -                w.append("      switch (type) {\n");
 114.304 -                for (int i = 0; i < propsGetSet.size(); i += 5) {
 114.305 -                    final String get = propsGetSet.get(i + 1);
 114.306 -                    if (get != null) {
 114.307 -                        w.append("        case " + (i / 5) + ": return data." + strip(get) + "();\n");
 114.308 -                    }
 114.309 -                }
 114.310 -                w.append("      }\n");
 114.311 -                w.append("      throw new UnsupportedOperationException();\n");
 114.312 -                w.append("    }\n");
 114.313 -                w.append("    public void call(" + className + " model, Object data, Object ev) {\n");
 114.314 -                w.append("      switch (type) {\n");
 114.315 -                for (int i = 0; i < functions.size(); i += 2) {
 114.316 -                    final String name = functions.get(i);
 114.317 -                    w.append("        case " + (i / 2) + ": model." + name + "(data, ev); return;\n");
 114.318 -                }
 114.319 -                w.append("      }\n");
 114.320 -                w.append("      throw new UnsupportedOperationException();\n");
 114.321 -                w.append("    }\n");
 114.322 -                w.append("    public Class<" + className + "> factoryFor() { return " + className + ".class; }\n");
 114.323 -                w.append("    public " + className + " read(net.java.html.BrwsrCtx c, Object json) { return new " + className + "(c, json); }\n");
 114.324 -                w.append("    public " + className + " cloneTo(Object o, net.java.html.BrwsrCtx c) { return ((" + className + ")o).clone(c); }\n");
 114.325 -                w.append("  }\n");
 114.326 -                w.append("  static { org.apidesign.html.json.impl.JSON.register(new P(0)); }\n");
 114.327 -                w.append("  private ").append(className).append("(net.java.html.BrwsrCtx c, Object json) {\n");
 114.328 -                w.append("    this.context = c;\n");
 114.329 -                int values = 0;
 114.330 -                for (int i = 0; i < propsGetSet.size(); i += 5) {
 114.331 -                    Prprt p = findPrprt(props, propsGetSet.get(i));
 114.332 -                    if (p == null) {
 114.333 -                        continue;
 114.334 -                    }
 114.335 -                    values++;
 114.336 -                }
 114.337 -                w.append("    Object[] ret = new Object[" + values + "];\n");
 114.338 -                w.append("    org.apidesign.html.json.impl.JSON.extract(context, json, new String[] {\n");
 114.339 -                for (int i = 0; i < propsGetSet.size(); i += 5) {
 114.340 -                    Prprt p = findPrprt(props, propsGetSet.get(i));
 114.341 -                    if (p == null) {
 114.342 -                        continue;
 114.343 -                    }
 114.344 -                    w.append("      \"").append(propsGetSet.get(i)).append("\",\n");
 114.345 -                }
 114.346 -                w.append("    }, ret);\n");
 114.347 -                for (int i = 0, cnt = 0, prop = 0; i < propsGetSet.size(); i += 5) {
 114.348 -                    final String pn = propsGetSet.get(i);
 114.349 -                    Prprt p = findPrprt(props, pn);
 114.350 -                    if (p == null) {
 114.351 -                        continue;
 114.352 -                    }
 114.353 -                    boolean[] isModel = { false };
 114.354 -                    boolean[] isEnum = { false };
 114.355 -                    boolean isPrimitive[] = { false };
 114.356 -                    String type = checkType(props[prop++], isModel, isEnum, isPrimitive);
 114.357 -                    if (p.array()) {
 114.358 -                        w.append("    if (ret[" + cnt + "] instanceof Object[]) {\n");
 114.359 -                        w.append("      for (Object e : ((Object[])ret[" + cnt + "])) {\n");
 114.360 -                        if (isModel[0]) {
 114.361 -                            w.append("        this.prop_").append(pn).append(".add(org.apidesign.html.json.impl.JSON.read");
 114.362 -                            w.append("(c, " + type + ".class, e));\n");
 114.363 -                        } else if (isEnum[0]) {
 114.364 -                            w.append("        this.prop_").append(pn);
 114.365 -                            w.append(".add(e == null ? null : ");
 114.366 -                            w.append(type).append(".valueOf(org.apidesign.html.json.impl.JSON.stringValue(e)));\n");
 114.367 -                        } else {
 114.368 -                            if (isPrimitive(type)) {
 114.369 -                                w.append("        this.prop_").append(pn).append(".add(org.apidesign.html.json.impl.JSON.numberValue(e).");
 114.370 -                                w.append(type).append("Value());\n");
 114.371 -                            } else {
 114.372 -                                w.append("        this.prop_").append(pn).append(".add((");
 114.373 -                                w.append(type).append(")e);\n");
 114.374 -                            }
 114.375 -                        }
 114.376 -                        w.append("      }\n");
 114.377 -                        w.append("    }\n");
 114.378 -                    } else {
 114.379 -                        if (isEnum[0]) {
 114.380 -                            w.append("    try {\n");
 114.381 -                            w.append("    this.prop_").append(pn);
 114.382 -                            w.append(" = ret[" + cnt + "] == null ? null : ");
 114.383 -                            w.append(type).append(".valueOf(org.apidesign.html.json.impl.JSON.stringValue(ret[" + cnt + "]));\n");
 114.384 -                            w.append("    } catch (IllegalArgumentException ex) {\n");
 114.385 -                            w.append("      ex.printStackTrace();\n");
 114.386 -                            w.append("    }\n");
 114.387 -                        } else if (isPrimitive(type)) {
 114.388 -                            w.append("    this.prop_").append(pn);
 114.389 -                            w.append(" = ret[" + cnt + "] == null ? ");
 114.390 -                            if ("char".equals(type)) {
 114.391 -                                w.append("0 : (org.apidesign.html.json.impl.JSON.charValue(");
 114.392 -                            } else if ("boolean".equals(type)) {
 114.393 -                                w.append("false : (org.apidesign.html.json.impl.JSON.boolValue(");
 114.394 -                            } else {
 114.395 -                                w.append("0 : (org.apidesign.html.json.impl.JSON.numberValue(");
 114.396 -                            }
 114.397 -                            w.append("ret[" + cnt + "])).");
 114.398 -                            w.append(type).append("Value();\n");
 114.399 -                        } else if (isModel[0]) {
 114.400 -                            w.append("    this.prop_").append(pn).append(" = org.apidesign.html.json.impl.JSON.read");
 114.401 -                            w.append("(c, " + type + ".class, ");
 114.402 -                            w.append("ret[" + cnt + "]);\n");
 114.403 -                        }else {
 114.404 -                            w.append("    this.prop_").append(pn);
 114.405 -                            w.append(" = (").append(type).append(')');
 114.406 -                            w.append("ret[" + cnt + "];\n");
 114.407 -                        }
 114.408 -                    }
 114.409 -                    cnt++;
 114.410 -                }
 114.411 -                w.append("  };\n");
 114.412 -                writeToString(props, w);
 114.413 -                writeClone(className, props, w);
 114.414 -                w.write("  /** Activates this model instance in the current {@link \n"
 114.415 -                    + "net.java.html.json.Models#bind(java.lang.Object, net.java.html.BrwsrCtx) browser context}. \n"
 114.416 -                    + "In case of using Knockout technology, this means to \n"
 114.417 -                    + "bind JSON like data in this model instance with Knockout tags in \n"
 114.418 -                    + "the surrounding HTML page.\n"
 114.419 -                    + "*/\n"
 114.420 -                );
 114.421 -                w.write("  public " + className + " applyBindings() {\n");
 114.422 -                w.write("    intKnckt().applyBindings();\n");
 114.423 -                w.write("    return this;\n");
 114.424 -                w.write("  }\n");
 114.425 -                w.write("  public boolean equals(Object o) {\n");
 114.426 -                w.write("    if (o == this) return true;\n");
 114.427 -                w.write("    if (o instanceof org.apidesign.html.json.impl.WrapperObject) {\n");
 114.428 -                w.write("      ((org.apidesign.html.json.impl.WrapperObject)o).setRealObject(intKnckt().koData());\n");
 114.429 -                w.write("      return false;\n");
 114.430 -                w.write("    }\n");
 114.431 -                w.write("    if (!(o instanceof " + className + ")) return false;\n");
 114.432 -                w.write("    " + className + " p = (" + className + ")o;\n");
 114.433 -                for (Prprt p : props) {
 114.434 -                    w.write("    if (!org.apidesign.html.json.impl.JSON.isSame(prop_" + p.name() + ", p.prop_" + p.name() + ")) return false;\n");
 114.435 -                }
 114.436 -                w.write("    return true;\n");
 114.437 -                w.write("  }\n");
 114.438 -                w.write("  public int hashCode() {\n");
 114.439 -                w.write("    int h = " + className + ".class.getName().hashCode();\n");
 114.440 -                for (Prprt p : props) {
 114.441 -                    w.write("    h = org.apidesign.html.json.impl.JSON.hashPlus(prop_" + p.name() + ", h);\n");
 114.442 -                }
 114.443 -                w.write("    return h;\n");
 114.444 -                w.write("  }\n");
 114.445 -                w.write("}\n");
 114.446 -            } finally {
 114.447 -                w.close();
 114.448 -            }
 114.449 -        } catch (IOException ex) {
 114.450 -            error("Can't create " + className + ".java", e);
 114.451 -            return false;
 114.452 -        }
 114.453 -        return ok;
 114.454 -    }
 114.455 -    
 114.456 -    private boolean generateProperties(
 114.457 -        Element where,
 114.458 -        Writer w, Prprt[] properties,
 114.459 -        Collection<String> props, 
 114.460 -        Map<String,Collection<String>> deps,
 114.461 -        Map<String,Collection<String>> functionDeps
 114.462 -    ) throws IOException {
 114.463 -        boolean ok = true;
 114.464 -        for (Prprt p : properties) {
 114.465 -            final String tn;
 114.466 -            tn = typeName(where, p);
 114.467 -            String[] gs = toGetSet(p.name(), tn, p.array());
 114.468 -            String castTo;
 114.469 -            
 114.470 -            if (p.array()) {
 114.471 -                w.write("  private org.apidesign.html.json.impl.JSONList<" + tn + "> prop_" + p.name() + " = new org.apidesign.html.json.impl.JSONList<" + tn + ">(ko, \""
 114.472 -                    + p.name() + "\"");
 114.473 -                Collection<String> dependants = deps.get(p.name());
 114.474 -                if (dependants != null) {
 114.475 -                    for (String depProp : dependants) {
 114.476 -                        w.write(", ");
 114.477 -                        w.write('\"');
 114.478 -                        w.write(depProp);
 114.479 -                        w.write('\"');
 114.480 -                    }
 114.481 -                }
 114.482 -                w.write(")");
 114.483 -                
 114.484 -                dependants = functionDeps.get(p.name());
 114.485 -                if (dependants != null) {
 114.486 -                    w.write(".onChange(new Runnable() { public void run() {\n");
 114.487 -                    for (String call : dependants) {
 114.488 -                        w.append("  ").append(call);
 114.489 -                    }
 114.490 -                    w.write("  }})");
 114.491 -                }
 114.492 -                w.write(";\n");
 114.493 -            
 114.494 -                castTo = "java.util.List";
 114.495 -                w.write("  public java.util.List<" + tn + "> " + gs[0] + "() {\n");
 114.496 -                w.write("    if (locked) throw new IllegalStateException();\n");
 114.497 -                w.write("    return prop_" + p.name() + ";\n");
 114.498 -                w.write("  }\n");
 114.499 -            } else {
 114.500 -                castTo = tn;
 114.501 -                w.write("  private " + tn + " prop_" + p.name() + ";\n");
 114.502 -                w.write("  public " + tn + " " + gs[0] + "() {\n");
 114.503 -                w.write("    if (locked) throw new IllegalStateException();\n");
 114.504 -                w.write("    return prop_" + p.name() + ";\n");
 114.505 -                w.write("  }\n");
 114.506 -                w.write("  public void " + gs[1] + "(" + tn + " v) {\n");
 114.507 -                w.write("    if (locked) throw new IllegalStateException();\n");
 114.508 -                w.write("    if (org.apidesign.html.json.impl.JSON.isSame(prop_" + p.name() + ", v)) return;\n");
 114.509 -                w.write("    prop_" + p.name() + " = v;\n");
 114.510 -                w.write("    org.apidesign.html.json.impl.Bindings b = ko[0];\n");
 114.511 -                w.write("    if (b != null) {\n");
 114.512 -                w.write("      b.valueHasMutated(\"" + p.name() + "\");\n");
 114.513 -                Collection<String> dependants = deps.get(p.name());
 114.514 -                if (dependants != null) {
 114.515 -                    for (String depProp : dependants) {
 114.516 -                        w.write("      b.valueHasMutated(\"" + depProp + "\");\n");
 114.517 -                    }
 114.518 -                }
 114.519 -                w.write("    }\n");
 114.520 -                dependants = functionDeps.get(p.name());
 114.521 -                if (dependants != null) {
 114.522 -                    for (String call : dependants) {
 114.523 -                        w.append("  ").append(call);
 114.524 -                    }
 114.525 -                }
 114.526 -                w.write("  }\n");
 114.527 -            }
 114.528 -            
 114.529 -            props.add(p.name());
 114.530 -            props.add(gs[2]);
 114.531 -            props.add(gs[3]);
 114.532 -            props.add(gs[0]);
 114.533 -            props.add(castTo);
 114.534 -        }
 114.535 -        return ok;
 114.536 -    }
 114.537 -
 114.538 -    private boolean generateComputedProperties(
 114.539 -        Writer w, Prprt[] fixedProps,
 114.540 -        Collection<? extends Element> arr, Collection<String> props,
 114.541 -        Map<String,Collection<String>> deps
 114.542 -    ) throws IOException {
 114.543 -        boolean ok = true;
 114.544 -        for (Element e : arr) {
 114.545 -            if (e.getKind() != ElementKind.METHOD) {
 114.546 -                continue;
 114.547 -            }
 114.548 -            if (e.getAnnotation(ComputedProperty.class) == null) {
 114.549 -                continue;
 114.550 -            }
 114.551 -            if (!e.getModifiers().contains(Modifier.STATIC)) {
 114.552 -                error("Method " + e.getSimpleName() + " has to be static when annotated by @ComputedProperty", e);
 114.553 -                ok = false;
 114.554 -                continue;
 114.555 -            }
 114.556 -            ExecutableElement ee = (ExecutableElement)e;
 114.557 -            final TypeMirror rt = ee.getReturnType();
 114.558 -            final Types tu = processingEnv.getTypeUtils();
 114.559 -            TypeMirror ert = tu.erasure(rt);
 114.560 -            String tn = fqn(ert, ee);
 114.561 -            boolean array = false;
 114.562 -            final TypeMirror toCheck;
 114.563 -            if (tn.equals("java.util.List")) {
 114.564 -                array = true;
 114.565 -                toCheck = ((DeclaredType)rt).getTypeArguments().get(0);
 114.566 -            } else {
 114.567 -                toCheck = rt;
 114.568 -            }
 114.569 -            
 114.570 -            final String sn = ee.getSimpleName().toString();
 114.571 -            
 114.572 -            if (toCheck.getKind().isPrimitive()) {
 114.573 -                // OK
 114.574 -            } else {
 114.575 -                TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
 114.576 -                TypeMirror enumType = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType();
 114.577 -
 114.578 -                if (tu.isSubtype(toCheck, stringType)) {
 114.579 -                    // OK
 114.580 -                } else if (tu.isSubtype(tu.erasure(toCheck), tu.erasure(enumType))) {
 114.581 -                    // OK
 114.582 -                } else if (isModel(toCheck)) {
 114.583 -                    // OK
 114.584 -                } else {
 114.585 -                    ok = false;
 114.586 -                    error(sn + " cannot return " + toCheck, e);
 114.587 -                }
 114.588 -            }
 114.589 -            
 114.590 -            String[] gs = toGetSet(sn, tn, array);
 114.591 -            
 114.592 -            w.write("  public " + tn + " " + gs[0] + "() {\n");
 114.593 -            w.write("    if (locked) throw new IllegalStateException();\n");
 114.594 -            int arg = 0;
 114.595 -            for (VariableElement pe : ee.getParameters()) {
 114.596 -                final String dn = pe.getSimpleName().toString();
 114.597 -                
 114.598 -                if (!verifyPropName(pe, dn, fixedProps)) {
 114.599 -                    ok = false;
 114.600 -                }
 114.601 -                
 114.602 -                final String dt = fqn(pe.asType(), ee);
 114.603 -                String[] call = toGetSet(dn, dt, false);
 114.604 -                w.write("    " + dt + " arg" + (++arg) + " = ");
 114.605 -                w.write(call[0] + "();\n");
 114.606 -                
 114.607 -                Collection<String> depends = deps.get(dn);
 114.608 -                if (depends == null) {
 114.609 -                    depends = new LinkedHashSet<String>();
 114.610 -                    deps.put(dn, depends);
 114.611 -                }
 114.612 -                depends.add(sn);
 114.613 -            }
 114.614 -            w.write("    try {\n");
 114.615 -            w.write("      locked = true;\n");
 114.616 -            w.write("      return " + fqn(ee.getEnclosingElement().asType(), ee) + '.' + e.getSimpleName() + "(");
 114.617 -            String sep = "";
 114.618 -            for (int i = 1; i <= arg; i++) {
 114.619 -                w.write(sep);
 114.620 -                w.write("arg" + i);
 114.621 -                sep = ", ";
 114.622 -            }
 114.623 -            w.write(");\n");
 114.624 -            w.write("    } finally {\n");
 114.625 -            w.write("      locked = false;\n");
 114.626 -            w.write("    }\n");
 114.627 -            w.write("  }\n");
 114.628 -
 114.629 -            props.add(e.getSimpleName().toString());
 114.630 -            props.add(gs[2]);
 114.631 -            props.add(null);
 114.632 -            props.add(gs[0]);
 114.633 -            props.add(tn);
 114.634 -        }
 114.635 -        
 114.636 -        return ok;
 114.637 -    }
 114.638 -
 114.639 -    private static String[] toGetSet(String name, String type, boolean array) {
 114.640 -        String n = Character.toUpperCase(name.charAt(0)) + name.substring(1);
 114.641 -        String bck2brwsrType = "L" + type.replace('.', '_') + "_2";
 114.642 -        if ("int".equals(type)) {
 114.643 -            bck2brwsrType = "I";
 114.644 -        }
 114.645 -        if ("double".equals(type)) {
 114.646 -            bck2brwsrType = "D";
 114.647 -        }
 114.648 -        String pref = "get";
 114.649 -        if ("boolean".equals(type)) {
 114.650 -            pref = "is";
 114.651 -            bck2brwsrType = "Z";
 114.652 -        }
 114.653 -        final String nu = n.replace('.', '_');
 114.654 -        if (array) {
 114.655 -            return new String[] { 
 114.656 -                "get" + n,
 114.657 -                null,
 114.658 -                "get" + nu + "__Ljava_util_List_2",
 114.659 -                null
 114.660 -            };
 114.661 -        }
 114.662 -        return new String[]{
 114.663 -            pref + n, 
 114.664 -            "set" + n, 
 114.665 -            pref + nu + "__" + bck2brwsrType,
 114.666 -            "set" + nu + "__V" + bck2brwsrType
 114.667 -        };
 114.668 -    }
 114.669 -
 114.670 -    private String typeName(Element where, Prprt p) {
 114.671 -        String ret;
 114.672 -        boolean[] isModel = { false };
 114.673 -        boolean[] isEnum = { false };
 114.674 -        boolean isPrimitive[] = { false };
 114.675 -        ret = checkType(p, isModel, isEnum, isPrimitive);
 114.676 -        if (p.array()) {
 114.677 -            String bt = findBoxedType(ret);
 114.678 -            if (bt != null) {
 114.679 -                return bt;
 114.680 -            }
 114.681 -        }
 114.682 -        return ret;
 114.683 -    }
 114.684 -    
 114.685 -    private static String findBoxedType(String ret) {
 114.686 -        if (ret.equals("boolean")) {
 114.687 -            return Boolean.class.getName();
 114.688 -        }
 114.689 -        if (ret.equals("byte")) {
 114.690 -            return Byte.class.getName();
 114.691 -        }
 114.692 -        if (ret.equals("short")) {
 114.693 -            return Short.class.getName();
 114.694 -        }
 114.695 -        if (ret.equals("char")) {
 114.696 -            return Character.class.getName();
 114.697 -        }
 114.698 -        if (ret.equals("int")) {
 114.699 -            return Integer.class.getName();
 114.700 -        }
 114.701 -        if (ret.equals("long")) {
 114.702 -            return Long.class.getName();
 114.703 -        }
 114.704 -        if (ret.equals("float")) {
 114.705 -            return Float.class.getName();
 114.706 -        }
 114.707 -        if (ret.equals("double")) {
 114.708 -            return Double.class.getName();
 114.709 -        }
 114.710 -        return null;
 114.711 -    }
 114.712 -
 114.713 -    private boolean verifyPropName(Element e, String propName, Prprt[] existingProps) {
 114.714 -        StringBuilder sb = new StringBuilder();
 114.715 -        String sep = "";
 114.716 -        for (Prprt Prprt : existingProps) {
 114.717 -            if (Prprt.name().equals(propName)) {
 114.718 -                return true;
 114.719 -            }
 114.720 -            sb.append(sep);
 114.721 -            sb.append('"');
 114.722 -            sb.append(Prprt.name());
 114.723 -            sb.append('"');
 114.724 -            sep = ", ";
 114.725 -        }
 114.726 -        error(
 114.727 -            propName + " is not one of known properties: " + sb
 114.728 -            , e
 114.729 -        );
 114.730 -        return false;
 114.731 -    }
 114.732 -
 114.733 -    private static String findPkgName(Element e) {
 114.734 -        for (;;) {
 114.735 -            if (e.getKind() == ElementKind.PACKAGE) {
 114.736 -                return ((PackageElement)e).getQualifiedName().toString();
 114.737 -            }
 114.738 -            e = e.getEnclosingElement();
 114.739 -        }
 114.740 -    }
 114.741 -
 114.742 -    private boolean generateFunctions(
 114.743 -        Element clazz, StringWriter body, String className, 
 114.744 -        List<? extends Element> enclosedElements, List<String> functions
 114.745 -    ) {
 114.746 -        for (Element m : enclosedElements) {
 114.747 -            if (m.getKind() != ElementKind.METHOD) {
 114.748 -                continue;
 114.749 -            }
 114.750 -            ExecutableElement e = (ExecutableElement)m;
 114.751 -            Function onF = e.getAnnotation(Function.class);
 114.752 -            if (onF == null) {
 114.753 -                continue;
 114.754 -            }
 114.755 -            if (!e.getModifiers().contains(Modifier.STATIC)) {
 114.756 -                error("@OnFunction method needs to be static", e);
 114.757 -                return false;
 114.758 -            }
 114.759 -            if (e.getModifiers().contains(Modifier.PRIVATE)) {
 114.760 -                error("@OnFunction method cannot be private", e);
 114.761 -                return false;
 114.762 -            }
 114.763 -            if (e.getReturnType().getKind() != TypeKind.VOID) {
 114.764 -                error("@OnFunction method should return void", e);
 114.765 -                return false;
 114.766 -            }
 114.767 -            String n = e.getSimpleName().toString();
 114.768 -            body.append("  private void ").append(n).append("(Object data, Object ev) {\n");
 114.769 -            body.append("    ").append(((TypeElement)clazz).getQualifiedName()).append(".").append(n).append("(");
 114.770 -            body.append(wrapParams(e, null, className, "ev", "data"));
 114.771 -            body.append(");\n");
 114.772 -            body.append("  }\n");
 114.773 -            
 114.774 -            functions.add(n);
 114.775 -            functions.add(n + "__VLjava_lang_Object_2Ljava_lang_Object_2");
 114.776 -        }
 114.777 -        return true;
 114.778 -    }
 114.779 -
 114.780 -    private boolean generateOnChange(Element clazz, Map<String,Collection<String>> propDeps,
 114.781 -        Prprt[] properties, String className, 
 114.782 -        Map<String, Collection<String>> functionDeps
 114.783 -    ) {
 114.784 -        for (Element m : clazz.getEnclosedElements()) {
 114.785 -            if (m.getKind() != ElementKind.METHOD) {
 114.786 -                continue;
 114.787 -            }
 114.788 -            ExecutableElement e = (ExecutableElement) m;
 114.789 -            OnPropertyChange onPC = e.getAnnotation(OnPropertyChange.class);
 114.790 -            if (onPC == null) {
 114.791 -                continue;
 114.792 -            }
 114.793 -            for (String pn : onPC.value()) {
 114.794 -                if (findPrprt(properties, pn) == null && findDerivedFrom(propDeps, pn).isEmpty()) {
 114.795 -                    error("No Prprt named '" + pn + "' in the model", clazz);
 114.796 -                    return false;
 114.797 -                }
 114.798 -            }
 114.799 -            if (!e.getModifiers().contains(Modifier.STATIC)) {
 114.800 -                error("@OnPrprtChange method needs to be static", e);
 114.801 -                return false;
 114.802 -            }
 114.803 -            if (e.getModifiers().contains(Modifier.PRIVATE)) {
 114.804 -                error("@OnPrprtChange method cannot be private", e);
 114.805 -                return false;
 114.806 -            }
 114.807 -            if (e.getReturnType().getKind() != TypeKind.VOID) {
 114.808 -                error("@OnPrprtChange method should return void", e);
 114.809 -                return false;
 114.810 -            }
 114.811 -            String n = e.getSimpleName().toString();
 114.812 -            
 114.813 -            
 114.814 -            for (String pn : onPC.value()) {
 114.815 -                StringBuilder call = new StringBuilder();
 114.816 -                call.append("  ").append(clazz.getSimpleName()).append(".").append(n).append("(");
 114.817 -                call.append(wrapPropName(e, className, "name", pn));
 114.818 -                call.append(");\n");
 114.819 -                
 114.820 -                Collection<String> change = functionDeps.get(pn);
 114.821 -                if (change == null) {
 114.822 -                    change = new ArrayList<String>();
 114.823 -                    functionDeps.put(pn, change);
 114.824 -                }
 114.825 -                change.add(call.toString());
 114.826 -                for (String dpn : findDerivedFrom(propDeps, pn)) {
 114.827 -                    change = functionDeps.get(dpn);
 114.828 -                    if (change == null) {
 114.829 -                        change = new ArrayList<String>();
 114.830 -                        functionDeps.put(dpn, change);
 114.831 -                    }
 114.832 -                    change.add(call.toString());
 114.833 -                }
 114.834 -            }
 114.835 -        }
 114.836 -        return true;
 114.837 -    }
 114.838 -
 114.839 -    private boolean generateOperation(Element clazz, 
 114.840 -        StringWriter body, String className, 
 114.841 -        List<? extends Element> enclosedElements
 114.842 -    ) {
 114.843 -        for (Element m : enclosedElements) {
 114.844 -            if (m.getKind() != ElementKind.METHOD) {
 114.845 -                continue;
 114.846 -            }
 114.847 -            ExecutableElement e = (ExecutableElement)m;
 114.848 -            ModelOperation mO = e.getAnnotation(ModelOperation.class);
 114.849 -            if (mO == null) {
 114.850 -                continue;
 114.851 -            }
 114.852 -            if (!e.getModifiers().contains(Modifier.STATIC)) {
 114.853 -                error("@ModelOperation method needs to be static", e);
 114.854 -                return false;
 114.855 -            }
 114.856 -            if (e.getModifiers().contains(Modifier.PRIVATE)) {
 114.857 -                error("@ModelOperation method cannot be private", e);
 114.858 -                return false;
 114.859 -            }
 114.860 -            if (e.getReturnType().getKind() != TypeKind.VOID) {
 114.861 -                error("@ModelOperation method should return void", e);
 114.862 -                return false;
 114.863 -            }
 114.864 -            List<String> args = new ArrayList<String>();
 114.865 -            {
 114.866 -                body.append("  public void ").append(m.getSimpleName()).append("(");
 114.867 -                String sep = "";
 114.868 -                boolean checkFirst = true;
 114.869 -                for (VariableElement ve : e.getParameters()) {
 114.870 -                    final TypeMirror type = ve.asType();
 114.871 -                    CharSequence simpleName;
 114.872 -                    if (type.getKind() == TypeKind.DECLARED) {
 114.873 -                        simpleName = ((DeclaredType)type).asElement().getSimpleName();
 114.874 -                    } else {
 114.875 -                        simpleName = type.toString();
 114.876 -                    }
 114.877 -                    if (simpleName.toString().equals(className)) {
 114.878 -                        checkFirst = false;
 114.879 -                    } else {
 114.880 -                        if (checkFirst) {
 114.881 -                            error("First parameter of @ModelOperation method must be " + className, m);
 114.882 -                            return false;
 114.883 -                        }
 114.884 -                        args.add(ve.getSimpleName().toString());
 114.885 -                        body.append(sep).append("final ");
 114.886 -                        body.append(ve.asType().toString()).append(" ");
 114.887 -                        body.append(ve.toString());
 114.888 -                        sep = ", ";
 114.889 -                    }
 114.890 -                }
 114.891 -                body.append(") {\n");
 114.892 -                body.append("    org.apidesign.html.json.impl.JSON.runInBrowser(this.context, new Runnable() { public void run() {\n");
 114.893 -                body.append("      ").append(clazz.getSimpleName()).append(".").append(m.getSimpleName()).append("(");
 114.894 -                body.append(className).append(".this");
 114.895 -                for (String s : args) {
 114.896 -                    body.append(", ").append(s);
 114.897 -                }
 114.898 -                body.append(");\n");
 114.899 -                body.append("    }});\n");
 114.900 -                body.append("  }\n");
 114.901 -            }
 114.902 -            
 114.903 -        }
 114.904 -        return true;
 114.905 -    }
 114.906 -    
 114.907 -    
 114.908 -    private boolean generateReceive(
 114.909 -        Element clazz, StringWriter body, String className, 
 114.910 -        List<? extends Element> enclosedElements, List<String> functions
 114.911 -    ) {
 114.912 -        for (Element m : enclosedElements) {
 114.913 -            if (m.getKind() != ElementKind.METHOD) {
 114.914 -                continue;
 114.915 -            }
 114.916 -            ExecutableElement e = (ExecutableElement)m;
 114.917 -            OnReceive onR = e.getAnnotation(OnReceive.class);
 114.918 -            if (onR == null) {
 114.919 -                continue;
 114.920 -            }
 114.921 -            if (!e.getModifiers().contains(Modifier.STATIC)) {
 114.922 -                error("@OnReceive method needs to be static", e);
 114.923 -                return false;
 114.924 -            }
 114.925 -            if (e.getModifiers().contains(Modifier.PRIVATE)) {
 114.926 -                error("@OnReceive method cannot be private", e);
 114.927 -                return false;
 114.928 -            }
 114.929 -            if (e.getReturnType().getKind() != TypeKind.VOID) {
 114.930 -                error("@OnReceive method should return void", e);
 114.931 -                return false;
 114.932 -            }
 114.933 -            if (!onR.jsonp().isEmpty() && !"GET".equals(onR.method())) {
 114.934 -                error("JSONP works only with GET transport method", e);
 114.935 -            }
 114.936 -            String dataMirror = findDataSpecified(e, onR);
 114.937 -            if ("PUT".equals(onR.method()) && dataMirror == null) {
 114.938 -                error("PUT method needs to specify a data() class", e);
 114.939 -                return false;
 114.940 -            }
 114.941 -            if ("POST".equals(onR.method()) && dataMirror == null) {
 114.942 -                error("POST method needs to specify a data() class", e);
 114.943 -                return false;
 114.944 -            }
 114.945 -            String modelClass = null;
 114.946 -            boolean expectsList = false;
 114.947 -            List<String> args = new ArrayList<String>();
 114.948 -            {
 114.949 -                for (VariableElement ve : e.getParameters()) {
 114.950 -                    TypeMirror modelType = null;
 114.951 -                    final TypeMirror type = ve.asType();
 114.952 -                    CharSequence simpleName;
 114.953 -                    if (type.getKind() == TypeKind.DECLARED) {
 114.954 -                        simpleName = ((DeclaredType)type).asElement().getSimpleName();
 114.955 -                    } else {
 114.956 -                        simpleName = type.toString();
 114.957 -                    }
 114.958 -                    if (simpleName.toString().equals(className)) {
 114.959 -                        args.add(className + ".this");
 114.960 -                    } else if (isModel(ve.asType())) {
 114.961 -                        modelType = ve.asType();
 114.962 -                    } else if (ve.asType().getKind() == TypeKind.ARRAY) {
 114.963 -                        modelType = ((ArrayType)ve.asType()).getComponentType();
 114.964 -                        expectsList = true;
 114.965 -                    } else if (ve.asType().toString().equals("java.lang.String")) {
 114.966 -                        modelType = ve.asType();
 114.967 -                    }
 114.968 -                    if (modelType != null) {
 114.969 -                        if (modelClass != null) {
 114.970 -                            error("There can be only one model class among arguments", e);
 114.971 -                        } else {
 114.972 -                            modelClass = modelType.toString();
 114.973 -                            if (expectsList) {
 114.974 -                                args.add("arr");
 114.975 -                            } else {
 114.976 -                                args.add("arr[0]");
 114.977 -                            }
 114.978 -                        }
 114.979 -                    }
 114.980 -                }
 114.981 -            }
 114.982 -            if (modelClass == null) {
 114.983 -                error("The method needs to have one @Model class as parameter", e);
 114.984 -            }
 114.985 -            String n = e.getSimpleName().toString();
 114.986 -            if ("WebSocket".equals(onR.method())) {
 114.987 -                body.append("  /** Performs WebSocket communication. Call with <code>null</code> data parameter\n");
 114.988 -                body.append("  * to open the connection (even if not required). Call with non-null data to\n");
 114.989 -                body.append("  * send messages to server. Call again with <code>null</code> data to close the socket.\n");
 114.990 -                body.append("  */\n");
 114.991 -            }
 114.992 -            body.append("  public void ").append(n).append("(");
 114.993 -            StringBuilder urlBefore = new StringBuilder();
 114.994 -            StringBuilder urlAfter = new StringBuilder();
 114.995 -            String jsonpVarName = null;
 114.996 -            {
 114.997 -                String sep = "";
 114.998 -                boolean skipJSONP = onR.jsonp().isEmpty();
 114.999 -                for (String p : findParamNames(e, onR.url(), onR.jsonp(), urlBefore, urlAfter)) {
114.1000 -                    if (!skipJSONP && p.equals(onR.jsonp())) {
114.1001 -                        skipJSONP = true;
114.1002 -                        jsonpVarName = p;
114.1003 -                        continue;
114.1004 -                    }
114.1005 -                    body.append(sep);
114.1006 -                    body.append("String ").append(p);
114.1007 -                    sep = ", ";
114.1008 -                }
114.1009 -                if (!skipJSONP) {
114.1010 -                    error(
114.1011 -                        "Name of jsonp attribute ('" + onR.jsonp() + 
114.1012 -                        "') is not used in url attribute '" + onR.url() + "'", e
114.1013 -                    );
114.1014 -                }
114.1015 -                if (dataMirror != null) {
114.1016 -                    body.append(sep).append(dataMirror.toString()).append(" data");
114.1017 -                }
114.1018 -            }
114.1019 -            body.append(") {\n");
114.1020 -            boolean webSocket = onR.method().equals("WebSocket");
114.1021 -            if (webSocket) {
114.1022 -                if (generateWSReceiveBody(body, onR, e, clazz, className, expectsList, modelClass, n, args, urlBefore, jsonpVarName, urlAfter, dataMirror)) {
114.1023 -                    return false;
114.1024 -                }
114.1025 -                body.append("  }\n");
114.1026 -                body.append("  private org.apidesign.html.json.impl.JSON.WS ws_" + e.getSimpleName() + ";\n");
114.1027 -            } else {
114.1028 -                if (generateJSONReceiveBody(body, onR, e, clazz, className, expectsList, modelClass, n, args, urlBefore, jsonpVarName, urlAfter, dataMirror)) {
114.1029 -                    return false;
114.1030 -                }
114.1031 -                body.append("  }\n");
114.1032 -            }
114.1033 -        }
114.1034 -        return true;
114.1035 -    }
114.1036 -
114.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) {
114.1038 -        body.append(
114.1039 -            "    class ProcessResult extends org.apidesign.html.json.impl.RcvrJSON {\n" +
114.1040 -            "      @Override\n" +
114.1041 -            "      public void onError(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n" +
114.1042 -            "        Exception value = ev.getException();\n"
114.1043 -            );
114.1044 -        if (onR.onError().isEmpty()) {
114.1045 -            body.append(
114.1046 -                "        value.printStackTrace();\n"
114.1047 -                );
114.1048 -        } else {
114.1049 -            if (!findOnError(e, ((TypeElement)clazz), onR.onError(), className)) {
114.1050 -                return true;
114.1051 -            }
114.1052 -            body.append("        ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
114.1053 -            body.append(className).append(".this, value);\n");
114.1054 -        }
114.1055 -        body.append(
114.1056 -            "      }\n" +
114.1057 -            "      @Override\n" +
114.1058 -            "      public void onMessage(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
114.1059 -            );
114.1060 -        if (expectsList) {
114.1061 -            body.append(
114.1062 -                "        " + modelClass + "[] arr = new " + modelClass + "[ev.dataSize()];\n"
114.1063 -                );
114.1064 -        } else {
114.1065 -            body.append(
114.1066 -                "        " + modelClass + "[] arr = { null };\n"
114.1067 -                );
114.1068 -        }
114.1069 -        body.append(
114.1070 -            "        ev.dataRead(context, " + modelClass + ".class, arr);\n"
114.1071 -            );
114.1072 -        {
114.1073 -            body.append("        ").append(clazz.getSimpleName()).append(".").append(n).append("(");
114.1074 -            String sep = "";
114.1075 -            for (String arg : args) {
114.1076 -                body.append(sep);
114.1077 -                body.append(arg);
114.1078 -                sep = ", ";
114.1079 -            }
114.1080 -            body.append(");\n");
114.1081 -        }
114.1082 -        body.append(
114.1083 -            "      }\n" +
114.1084 -            "    }\n"
114.1085 -            );
114.1086 -        body.append("    ProcessResult pr = new ProcessResult();\n");
114.1087 -        body.append("    org.apidesign.html.json.impl.JSON.loadJSON(context, pr,\n        ");
114.1088 -        body.append(urlBefore).append(", ");
114.1089 -        if (jsonpVarName != null) {
114.1090 -            body.append(urlAfter);
114.1091 -        } else {
114.1092 -            body.append("null");
114.1093 -        }
114.1094 -        if (!"GET".equals(onR.method()) || dataMirror != null) {
114.1095 -            body.append(", \"").append(onR.method()).append('"');
114.1096 -            if (dataMirror != null) {
114.1097 -                body.append(", data");
114.1098 -            } else {
114.1099 -                body.append(", null");
114.1100 -            }
114.1101 -        } else {
114.1102 -            body.append(", null, null");
114.1103 -        }
114.1104 -        body.append(");\n");
114.1105 -        return false;
114.1106 -    }
114.1107 -    
114.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) {
114.1109 -        body.append(
114.1110 -            "    class ProcessResult extends org.apidesign.html.json.impl.RcvrJSON {\n" +
114.1111 -            "      @Override\n" +
114.1112 -            "      public void onOpen(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
114.1113 -        );
114.1114 -        body.append("        ").append(clazz.getSimpleName()).append(".").append(n).append("(");
114.1115 -        {
114.1116 -            String sep = "";
114.1117 -            for (String arg : args) {
114.1118 -                body.append(sep);
114.1119 -                if (arg.startsWith("arr")) {
114.1120 -                    body.append("null");
114.1121 -                } else {
114.1122 -                    body.append(arg);
114.1123 -                }
114.1124 -                sep = ", ";
114.1125 -            }
114.1126 -        }
114.1127 -        body.append(");\n");
114.1128 -        body.append(
114.1129 -            "      }\n" +
114.1130 -            "      @Override\n" +
114.1131 -            "      public void onError(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n" +
114.1132 -            "        Exception value = ev.getException();\n"
114.1133 -            );
114.1134 -        if (onR.onError().isEmpty()) {
114.1135 -            body.append(
114.1136 -                "        value.printStackTrace();\n"
114.1137 -                );
114.1138 -        } else {
114.1139 -            if (!findOnError(e, ((TypeElement)clazz), onR.onError(), className)) {
114.1140 -                return true;
114.1141 -            }
114.1142 -            body.append("        ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
114.1143 -            body.append(className).append(".this, value);\n");
114.1144 -        }
114.1145 -        body.append(
114.1146 -            "      }\n" +
114.1147 -            "      @Override\n" +
114.1148 -            "      public void onMessage(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
114.1149 -        );
114.1150 -        if (expectsList) {
114.1151 -            body.append(
114.1152 -                "        " + modelClass + "[] arr = new " + modelClass + "[ev.dataSize()];\n"
114.1153 -                );
114.1154 -        } else {
114.1155 -            body.append(
114.1156 -                "        " + modelClass + "[] arr = { null };\n"
114.1157 -                );
114.1158 -        }
114.1159 -        body.append(
114.1160 -            "        ev.dataRead(context, " + modelClass + ".class, arr);\n"
114.1161 -            );
114.1162 -        {
114.1163 -            body.append("        ").append(clazz.getSimpleName()).append(".").append(n).append("(");
114.1164 -            String sep = "";
114.1165 -            for (String arg : args) {
114.1166 -                body.append(sep);
114.1167 -                body.append(arg);
114.1168 -                sep = ", ";
114.1169 -            }
114.1170 -            body.append(");\n");
114.1171 -        }
114.1172 -        body.append(
114.1173 -            "      }\n"
114.1174 -        );
114.1175 -        if (!onR.onError().isEmpty()) {
114.1176 -            body.append(
114.1177 -                "      @Override\n"
114.1178 -              + "      public void onClose(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
114.1179 -            );
114.1180 -            body.append("        ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
114.1181 -            body.append(className).append(".this, null);\n");
114.1182 -            body.append(
114.1183 -                "      }\n"
114.1184 -            );
114.1185 -        }
114.1186 -        body.append("    }\n");
114.1187 -        body.append("    if (this.ws_").append(e.getSimpleName()).append(" == null) {\n");
114.1188 -        body.append("      ProcessResult pr = new ProcessResult();\n");
114.1189 -        body.append("      this.ws_").append(e.getSimpleName());
114.1190 -        body.append("= org.apidesign.html.json.impl.JSON.openWS(context, pr,\n        ");
114.1191 -        body.append(urlBefore).append(", data);\n");
114.1192 -        body.append("    } else {\n");
114.1193 -        body.append("      this.ws_").append(e.getSimpleName()).append(".send(context, ").append(urlBefore).append(", data);\n");
114.1194 -        body.append("    }\n");
114.1195 -        return false;
114.1196 -    }
114.1197 -
114.1198 -    private CharSequence wrapParams(
114.1199 -        ExecutableElement ee, String id, String className, String evName, String dataName
114.1200 -    ) {
114.1201 -        TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
114.1202 -        StringBuilder params = new StringBuilder();
114.1203 -        boolean first = true;
114.1204 -        for (VariableElement ve : ee.getParameters()) {
114.1205 -            if (!first) {
114.1206 -                params.append(", ");
114.1207 -            }
114.1208 -            first = false;
114.1209 -            String toCall = null;
114.1210 -            String toFinish = null;
114.1211 -            if (ve.asType() == stringType) {
114.1212 -                if (ve.getSimpleName().contentEquals("id")) {
114.1213 -                    params.append('"').append(id).append('"');
114.1214 -                    continue;
114.1215 -                }
114.1216 -                toCall = "org.apidesign.html.json.impl.JSON.toString(context, ";
114.1217 -            }
114.1218 -            if (ve.asType().getKind() == TypeKind.DOUBLE) {
114.1219 -                toCall = "org.apidesign.html.json.impl.JSON.toNumber(context, ";
114.1220 -                toFinish = ".doubleValue()";
114.1221 -            }
114.1222 -            if (ve.asType().getKind() == TypeKind.INT) {
114.1223 -                toCall = "org.apidesign.html.json.impl.JSON.toNumber(context, ";
114.1224 -                toFinish = ".intValue()";
114.1225 -            }
114.1226 -            if (dataName != null && ve.getSimpleName().contentEquals(dataName) && isModel(ve.asType())) {
114.1227 -                toCall = "org.apidesign.html.json.impl.JSON.toModel(context, " + ve.asType() + ".class, ";
114.1228 -            }
114.1229 -
114.1230 -            if (toCall != null) {
114.1231 -                params.append(toCall);
114.1232 -                if (dataName != null && ve.getSimpleName().contentEquals(dataName)) {
114.1233 -                    params.append(dataName);
114.1234 -                    params.append(", null");
114.1235 -                } else {
114.1236 -                    if (evName == null) {
114.1237 -                        final StringBuilder sb = new StringBuilder();
114.1238 -                        sb.append("Unexpected string parameter name.");
114.1239 -                        if (dataName != null) {
114.1240 -                            sb.append(" Try \"").append(dataName).append("\"");
114.1241 -                        }
114.1242 -                        error(sb.toString(), ee);
114.1243 -                    }
114.1244 -                    params.append(evName);
114.1245 -                    params.append(", \"");
114.1246 -                    params.append(ve.getSimpleName().toString());
114.1247 -                    params.append("\"");
114.1248 -                }
114.1249 -                params.append(")");
114.1250 -                if (toFinish != null) {
114.1251 -                    params.append(toFinish);
114.1252 -                }
114.1253 -                continue;
114.1254 -            }
114.1255 -            String rn = fqn(ve.asType(), ee);
114.1256 -            int last = rn.lastIndexOf('.');
114.1257 -            if (last >= 0) {
114.1258 -                rn = rn.substring(last + 1);
114.1259 -            }
114.1260 -            if (rn.equals(className)) {
114.1261 -                params.append(className).append(".this");
114.1262 -                continue;
114.1263 -            }
114.1264 -            error(
114.1265 -                "The annotated method can only accept " + className + " argument or argument named 'data'",
114.1266 -                ee
114.1267 -            );
114.1268 -        }
114.1269 -        return params;
114.1270 -    }
114.1271 -    
114.1272 -    
114.1273 -    private CharSequence wrapPropName(
114.1274 -        ExecutableElement ee, String className, String propName, String propValue
114.1275 -    ) {
114.1276 -        TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
114.1277 -        StringBuilder params = new StringBuilder();
114.1278 -        boolean first = true;
114.1279 -        for (VariableElement ve : ee.getParameters()) {
114.1280 -            if (!first) {
114.1281 -                params.append(", ");
114.1282 -            }
114.1283 -            first = false;
114.1284 -            if (ve.asType() == stringType) {
114.1285 -                if (propName != null && ve.getSimpleName().contentEquals(propName)) {
114.1286 -                    params.append('"').append(propValue).append('"');
114.1287 -                } else {
114.1288 -                    error("Unexpected string parameter name. Try \"" + propName + "\".", ee);
114.1289 -                }
114.1290 -                continue;
114.1291 -            }
114.1292 -            String rn = fqn(ve.asType(), ee);
114.1293 -            int last = rn.lastIndexOf('.');
114.1294 -            if (last >= 0) {
114.1295 -                rn = rn.substring(last + 1);
114.1296 -            }
114.1297 -            if (rn.equals(className)) {
114.1298 -                params.append(className).append(".this");
114.1299 -                continue;
114.1300 -            }
114.1301 -            error(
114.1302 -                "@OnPrprtChange method can only accept String or " + className + " arguments",
114.1303 -                ee);
114.1304 -        }
114.1305 -        return params;
114.1306 -    }
114.1307 -    
114.1308 -    private boolean isModel(TypeMirror tm) {
114.1309 -        if (tm.getKind() == TypeKind.ERROR) {
114.1310 -            return true;
114.1311 -        }
114.1312 -        final Element e = processingEnv.getTypeUtils().asElement(tm);
114.1313 -        if (e == null) {
114.1314 -            return false;
114.1315 -        }
114.1316 -        for (Element ch : e.getEnclosedElements()) {
114.1317 -            if (ch.getKind() == ElementKind.METHOD) {
114.1318 -                ExecutableElement ee = (ExecutableElement)ch;
114.1319 -                if (ee.getParameters().isEmpty() && ee.getSimpleName().contentEquals("modelFor")) {
114.1320 -                    return true;
114.1321 -                }
114.1322 -            }
114.1323 -        }
114.1324 -        return models.values().contains(e.getSimpleName().toString());
114.1325 -    }
114.1326 -    
114.1327 -    private void writeToString(Prprt[] props, Writer w) throws IOException {
114.1328 -        w.write("  public String toString() {\n");
114.1329 -        w.write("    StringBuilder sb = new StringBuilder();\n");
114.1330 -        w.write("    sb.append('{');\n");
114.1331 -        String sep = "";
114.1332 -        for (Prprt p : props) {
114.1333 -            w.write(sep);
114.1334 -            w.append("    sb.append('\"').append(\"" + p.name() + "\")");
114.1335 -                w.append(".append('\"').append(\":\");\n");
114.1336 -            w.append("    sb.append(org.apidesign.html.json.impl.JSON.toJSON(prop_");
114.1337 -            w.append(p.name()).append("));\n");
114.1338 -            sep =    "    sb.append(',');\n";
114.1339 -        }
114.1340 -        w.write("    sb.append('}');\n");
114.1341 -        w.write("    return sb.toString();\n");
114.1342 -        w.write("  }\n");
114.1343 -    }
114.1344 -    private void writeClone(String className, Prprt[] props, Writer w) throws IOException {
114.1345 -        w.write("  public " + className + " clone() {\n");
114.1346 -        w.write("    return clone(context);\n");
114.1347 -        w.write("  }\n");
114.1348 -        w.write("  private " + className + " clone(net.java.html.BrwsrCtx ctx) {\n");
114.1349 -        w.write("    " + className + " ret = new " + className + "(ctx);\n");
114.1350 -        for (Prprt p : props) {
114.1351 -            if (!p.array()) {
114.1352 -                boolean isModel[] = { false };
114.1353 -                boolean isEnum[] = { false };
114.1354 -                boolean isPrimitive[] = { false };
114.1355 -                checkType(p, isModel, isEnum, isPrimitive);
114.1356 -                if (!isModel[0]) {
114.1357 -                    w.write("    ret.prop_" + p.name() + " = prop_" + p.name() + ";\n");
114.1358 -                    continue;
114.1359 -                }
114.1360 -                w.write("    ret.prop_" + p.name() + " =  prop_" + p.name() + "  == null ? null : prop_" + p.name() + ".clone();\n");
114.1361 -            } else {
114.1362 -                w.write("    ret.prop_" + p.name() + ".cloneAll(ctx, prop_" + p.name() + ");\n");
114.1363 -            }
114.1364 -        }
114.1365 -        
114.1366 -        w.write("    return ret;\n");
114.1367 -        w.write("  }\n");
114.1368 -    }
114.1369 -
114.1370 -    private String inPckName(Element e) {
114.1371 -        StringBuilder sb = new StringBuilder();
114.1372 -        while (e.getKind() != ElementKind.PACKAGE) {
114.1373 -            if (sb.length() == 0) {
114.1374 -                sb.append(e.getSimpleName());
114.1375 -            } else {
114.1376 -                sb.insert(0, '.');
114.1377 -                sb.insert(0, e.getSimpleName());
114.1378 -            }
114.1379 -            e = e.getEnclosingElement();
114.1380 -        }
114.1381 -        return sb.toString();
114.1382 -    }
114.1383 -
114.1384 -    private String fqn(TypeMirror pt, Element relative) {
114.1385 -        if (pt.getKind() == TypeKind.ERROR) {
114.1386 -            final Elements eu = processingEnv.getElementUtils();
114.1387 -            PackageElement pckg = eu.getPackageOf(relative);
114.1388 -            return pckg.getQualifiedName() + "." + pt.toString();
114.1389 -        }
114.1390 -        return pt.toString();
114.1391 -    }
114.1392 -
114.1393 -    private String checkType(Prprt p, boolean[] isModel, boolean[] isEnum, boolean[] isPrimitive) {
114.1394 -        TypeMirror tm;
114.1395 -        try {
114.1396 -            String ret = p.typeName(processingEnv);
114.1397 -            TypeElement e = processingEnv.getElementUtils().getTypeElement(ret);
114.1398 -            if (e == null) {
114.1399 -                isModel[0] = true;
114.1400 -                isEnum[0] = false;
114.1401 -                isPrimitive[0] = false;
114.1402 -                return ret;
114.1403 -            }
114.1404 -            tm = e.asType();
114.1405 -        } catch (MirroredTypeException ex) {
114.1406 -            tm = ex.getTypeMirror();
114.1407 -        }
114.1408 -        tm = processingEnv.getTypeUtils().erasure(tm);
114.1409 -        if (isPrimitive[0] = tm.getKind().isPrimitive()) {
114.1410 -            isEnum[0] = false;
114.1411 -            isModel[0] = false;
114.1412 -            return tm.toString();
114.1413 -        }
114.1414 -        final Element e = processingEnv.getTypeUtils().asElement(tm);
114.1415 -        if (e.getKind() == ElementKind.CLASS && tm.getKind() == TypeKind.ERROR) {
114.1416 -            isModel[0] = true;
114.1417 -            isEnum[0] = false;
114.1418 -            return e.getSimpleName().toString();
114.1419 -        }
114.1420 -        
114.1421 -        final Model m = e == null ? null : e.getAnnotation(Model.class);
114.1422 -        String ret;
114.1423 -        if (m != null) {
114.1424 -            ret = findPkgName(e) + '.' + m.className();
114.1425 -            isModel[0] = true;
114.1426 -            models.put(e, m.className());
114.1427 -        } else if (findModelForMthd(e)) {
114.1428 -            ret = ((TypeElement)e).getQualifiedName().toString();
114.1429 -            isModel[0] = true;
114.1430 -        } else {
114.1431 -            ret = tm.toString();
114.1432 -        }
114.1433 -        TypeMirror enm = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType();
114.1434 -        enm = processingEnv.getTypeUtils().erasure(enm);
114.1435 -        isEnum[0] = processingEnv.getTypeUtils().isSubtype(tm, enm);
114.1436 -        return ret;
114.1437 -    }
114.1438 -    
114.1439 -    private static boolean findModelForMthd(Element clazz) {
114.1440 -        if (clazz == null) {
114.1441 -            return false;
114.1442 -        }
114.1443 -        for (Element e : clazz.getEnclosedElements()) {
114.1444 -            if (e.getKind() == ElementKind.METHOD) {
114.1445 -                ExecutableElement ee = (ExecutableElement)e;
114.1446 -                if (
114.1447 -                    ee.getSimpleName().contentEquals("modelFor") &&
114.1448 -                    ee.getParameters().isEmpty()
114.1449 -                ) {
114.1450 -                    return true;
114.1451 -                }
114.1452 -            }
114.1453 -        }
114.1454 -        return false;
114.1455 -    }
114.1456 -
114.1457 -    private Iterable<String> findParamNames(
114.1458 -        Element e, String url, String jsonParam, StringBuilder... both
114.1459 -    ) {
114.1460 -        List<String> params = new ArrayList<String>();
114.1461 -        int wasJSON = 0;
114.1462 -
114.1463 -        for (int pos = 0; ;) {
114.1464 -            int next = url.indexOf('{', pos);
114.1465 -            if (next == -1) {
114.1466 -                both[wasJSON].append('"')
114.1467 -                    .append(url.substring(pos))
114.1468 -                    .append('"');
114.1469 -                return params;
114.1470 -            }
114.1471 -            int close = url.indexOf('}', next);
114.1472 -            if (close == -1) {
114.1473 -                error("Unbalanced '{' and '}' in " + url, e);
114.1474 -                return params;
114.1475 -            }
114.1476 -            final String paramName = url.substring(next + 1, close);
114.1477 -            params.add(paramName);
114.1478 -            if (paramName.equals(jsonParam) && !jsonParam.isEmpty()) {
114.1479 -                both[wasJSON].append('"')
114.1480 -                    .append(url.substring(pos, next))
114.1481 -                    .append('"');
114.1482 -                wasJSON = 1;
114.1483 -            } else {
114.1484 -                both[wasJSON].append('"')
114.1485 -                    .append(url.substring(pos, next))
114.1486 -                    .append("\" + ").append(paramName).append(" + ");
114.1487 -            }
114.1488 -            pos = close + 1;
114.1489 -        }
114.1490 -    }
114.1491 -
114.1492 -    private static Prprt findPrprt(Prprt[] properties, String propName) {
114.1493 -        for (Prprt p : properties) {
114.1494 -            if (propName.equals(p.name())) {
114.1495 -                return p;
114.1496 -            }
114.1497 -        }
114.1498 -        return null;
114.1499 -    }
114.1500 -
114.1501 -    private boolean isPrimitive(String type) {
114.1502 -        return 
114.1503 -            "int".equals(type) ||
114.1504 -            "double".equals(type) ||
114.1505 -            "long".equals(type) ||
114.1506 -            "short".equals(type) ||
114.1507 -            "byte".equals(type) ||
114.1508 -            "char".equals(type) ||
114.1509 -            "boolean".equals(type) ||
114.1510 -            "float".equals(type);
114.1511 -    }
114.1512 -
114.1513 -    private static Collection<String> findDerivedFrom(Map<String, Collection<String>> propsDeps, String derivedProp) {
114.1514 -        Set<String> names = new HashSet<String>();
114.1515 -        for (Map.Entry<String, Collection<String>> e : propsDeps.entrySet()) {
114.1516 -            if (e.getValue().contains(derivedProp)) {
114.1517 -                names.add(e.getKey());
114.1518 -            }
114.1519 -        }
114.1520 -        return names;
114.1521 -    }
114.1522 -    
114.1523 -    private Prprt[] createProps(Element e, Property[] arr) {
114.1524 -        Prprt[] ret = Prprt.wrap(processingEnv, e, arr);
114.1525 -        Prprt[] prev = verify.put(e, ret);
114.1526 -        if (prev != null) {
114.1527 -            error("Two sets of properties for ", e);
114.1528 -        }
114.1529 -        return ret;
114.1530 -    }
114.1531 -    
114.1532 -    private static String strip(String s) {
114.1533 -        int indx = s.indexOf("__");
114.1534 -        if (indx >= 0) {
114.1535 -            return s.substring(0, indx);
114.1536 -        } else {
114.1537 -            return s;
114.1538 -        }
114.1539 -    }
114.1540 -
114.1541 -    private String findDataSpecified(ExecutableElement e, OnReceive onR) {
114.1542 -        try {
114.1543 -            return onR.data().getName();
114.1544 -        } catch (MirroredTypeException ex) {
114.1545 -            final TypeMirror tm = ex.getTypeMirror();
114.1546 -            String name;
114.1547 -            final Element te = processingEnv.getTypeUtils().asElement(tm);
114.1548 -            if (te.getKind() == ElementKind.CLASS && tm.getKind() == TypeKind.ERROR) {
114.1549 -                name = te.getSimpleName().toString();
114.1550 -            } else {
114.1551 -                name = tm.toString();
114.1552 -            }
114.1553 -            return "java.lang.Object".equals(name) ? null : name;
114.1554 -        } catch (Exception ex) {
114.1555 -            // fallback
114.1556 -        }
114.1557 -        
114.1558 -        AnnotationMirror found = null;
114.1559 -        for (AnnotationMirror am : e.getAnnotationMirrors()) {
114.1560 -            if (am.getAnnotationType().toString().equals(OnReceive.class.getName())) {
114.1561 -                found = am;
114.1562 -            }
114.1563 -        }
114.1564 -        if (found == null) {
114.1565 -            return null;
114.1566 -        }
114.1567 -        
114.1568 -        for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : found.getElementValues().entrySet()) {
114.1569 -            ExecutableElement ee = entry.getKey();
114.1570 -            AnnotationValue av = entry.getValue();
114.1571 -            if (ee.getSimpleName().contentEquals("data")) {
114.1572 -                List<? extends Object> values = getAnnoValues(processingEnv, e, found);
114.1573 -                for (Object v : values) {
114.1574 -                    String sv = v.toString();
114.1575 -                    if (sv.startsWith("data = ") && sv.endsWith(".class")) {
114.1576 -                        return sv.substring(7, sv.length() - 6);
114.1577 -                    }
114.1578 -                }
114.1579 -                return "error";
114.1580 -            }
114.1581 -        }
114.1582 -        return null;
114.1583 -    }
114.1584 -
114.1585 -    static List<? extends Object> getAnnoValues(ProcessingEnvironment pe, Element e, AnnotationMirror am) {
114.1586 -        try {
114.1587 -            Class<?> trees = Class.forName("com.sun.tools.javac.api.JavacTrees");
114.1588 -            Method m = trees.getMethod("instance", ProcessingEnvironment.class);
114.1589 -            Object instance = m.invoke(null, pe);
114.1590 -            m = instance.getClass().getMethod("getPath", Element.class, AnnotationMirror.class);
114.1591 -            Object path = m.invoke(instance, e, am);
114.1592 -            m = path.getClass().getMethod("getLeaf");
114.1593 -            Object leaf = m.invoke(path);
114.1594 -            m = leaf.getClass().getMethod("getArguments");
114.1595 -            return (List) m.invoke(leaf);
114.1596 -        } catch (Exception ex) {
114.1597 -            return Collections.emptyList();
114.1598 -        }
114.1599 -    }
114.1600 -
114.1601 -    private static class Prprt {
114.1602 -        private final Element e;
114.1603 -        private final AnnotationMirror tm;
114.1604 -        private final Property p;
114.1605 -
114.1606 -        public Prprt(Element e, AnnotationMirror tm, Property p) {
114.1607 -            this.e = e;
114.1608 -            this.tm = tm;
114.1609 -            this.p = p;
114.1610 -        }
114.1611 -        
114.1612 -        String name() {
114.1613 -            return p.name();
114.1614 -        }
114.1615 -        
114.1616 -        boolean array() {
114.1617 -            return p.array();
114.1618 -        }
114.1619 -
114.1620 -        String typeName(ProcessingEnvironment env) {
114.1621 -            RuntimeException ex;
114.1622 -            try {
114.1623 -                return p.type().getName();
114.1624 -            } catch (IncompleteAnnotationException e) {
114.1625 -                ex = e;
114.1626 -            } catch (AnnotationTypeMismatchException e) {
114.1627 -                ex = e;
114.1628 -            }
114.1629 -            for (Object v : getAnnoValues(env, e, tm)) {
114.1630 -                String s = v.toString().replace(" ", "");
114.1631 -                if (s.startsWith("type=") && s.endsWith(".class")) {
114.1632 -                    return s.substring(5, s.length() - 6);
114.1633 -                }
114.1634 -            }
114.1635 -            throw ex;
114.1636 -        }
114.1637 -        
114.1638 -        
114.1639 -        static Prprt[] wrap(ProcessingEnvironment pe, Element e, Property[] arr) {
114.1640 -            if (arr.length == 0) {
114.1641 -                return new Prprt[0];
114.1642 -            }
114.1643 -            
114.1644 -            if (e.getKind() != ElementKind.CLASS) {
114.1645 -                throw new IllegalStateException("" + e.getKind());
114.1646 -            }
114.1647 -            TypeElement te = (TypeElement)e;
114.1648 -            List<? extends AnnotationValue> val = null;
114.1649 -            for (AnnotationMirror an : te.getAnnotationMirrors()) {
114.1650 -                for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : an.getElementValues().entrySet()) {
114.1651 -                    if (entry.getKey().getSimpleName().contentEquals("properties")) {
114.1652 -                        val = (List)entry.getValue().getValue();
114.1653 -                        break;
114.1654 -                    }
114.1655 -                }
114.1656 -            }
114.1657 -            if (val == null || val.size() != arr.length) {
114.1658 -                pe.getMessager().printMessage(Diagnostic.Kind.ERROR, "" + val, e);
114.1659 -                return new Prprt[0];
114.1660 -            }
114.1661 -            Prprt[] ret = new Prprt[arr.length];
114.1662 -            BIG: for (int i = 0; i < ret.length; i++) {
114.1663 -                AnnotationMirror am = (AnnotationMirror)val.get(i).getValue();
114.1664 -                ret[i] = new Prprt(e, am, arr[i]);
114.1665 -                
114.1666 -            }
114.1667 -            return ret;
114.1668 -        }
114.1669 -    }
114.1670 -
114.1671 -    @Override
114.1672 -    public Iterable<? extends Completion> getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) {
114.1673 -        final Level l = Level.FINE;
114.1674 -        LOG.log(l, " element: {0}", element);
114.1675 -        LOG.log(l, " annotation: {0}", annotation);
114.1676 -        LOG.log(l, " member: {0}", member);
114.1677 -        LOG.log(l, " userText: {0}", userText);
114.1678 -        LOG.log(l, "str: {0}", annotation.getAnnotationType().toString());
114.1679 -        if (annotation.getAnnotationType().toString().equals(OnReceive.class.getName())) {
114.1680 -            if (member.getSimpleName().contentEquals("method")) {
114.1681 -                return Arrays.asList(
114.1682 -                    methodOf("GET"),
114.1683 -                    methodOf("POST"),
114.1684 -                    methodOf("PUT"),
114.1685 -                    methodOf("DELETE"),
114.1686 -                    methodOf("HEAD"),
114.1687 -                    methodOf("WebSocket")
114.1688 -                );
114.1689 -            }
114.1690 -        }
114.1691 -        
114.1692 -        return super.getCompletions(element, annotation, member, userText);
114.1693 -    }
114.1694 -    
114.1695 -    private static final Completion methodOf(String method) {
114.1696 -        ResourceBundle rb = ResourceBundle.getBundle("org.apidesign.html.json.impl.Bundle");
114.1697 -        return Completions.of('"' + method + '"', rb.getString("MSG_Completion_" + method));
114.1698 -    }
114.1699 -    
114.1700 -    private boolean findOnError(ExecutableElement errElem, TypeElement te, String name, String className) {
114.1701 -        String err = null;
114.1702 -        METHODS:
114.1703 -        for (Element e : te.getEnclosedElements()) {
114.1704 -            if (e.getKind() != ElementKind.METHOD) {
114.1705 -                continue;
114.1706 -            }
114.1707 -            if (!e.getSimpleName().contentEquals(name)) {
114.1708 -                continue;
114.1709 -            }
114.1710 -            if (!e.getModifiers().contains(Modifier.STATIC)) {
114.1711 -                errElem = (ExecutableElement) e;
114.1712 -                err = "Would have to be static";
114.1713 -                continue;
114.1714 -            }
114.1715 -            ExecutableElement ee = (ExecutableElement) e;
114.1716 -            TypeMirror excType = processingEnv.getElementUtils().getTypeElement(Exception.class.getName()).asType();
114.1717 -            final List<? extends VariableElement> params = ee.getParameters();
114.1718 -            boolean error = false;
114.1719 -            if (params.size() != 2) {
114.1720 -                error = true;
114.1721 -            } else {
114.1722 -                String firstType = params.get(0).asType().toString();
114.1723 -                int lastDot = firstType.lastIndexOf('.');
114.1724 -                if (lastDot != -1) {
114.1725 -                    firstType = firstType.substring(lastDot + 1);
114.1726 -                }
114.1727 -                if (!firstType.equals(className)) {
114.1728 -                    error = true;
114.1729 -                }
114.1730 -                if (!processingEnv.getTypeUtils().isAssignable(excType, params.get(1).asType())) {
114.1731 -                    error = true;
114.1732 -                }
114.1733 -            }
114.1734 -            if (error) {
114.1735 -                errElem = (ExecutableElement) e;
114.1736 -                err = "Error method first argument needs to be " + className + " and second Exception";
114.1737 -                continue;
114.1738 -            }
114.1739 -            return true;
114.1740 -        }
114.1741 -        if (err == null) {
114.1742 -            err = "Cannot find " + name + "(" + className + ", Exception) method in this class";
114.1743 -        }
114.1744 -        error(err, errElem);
114.1745 -        return false;
114.1746 -    }
114.1747 -    
114.1748 -}
   115.1 --- a/json/src/main/java/org/apidesign/html/json/impl/PropertyBindingAccessor.java	Mon Dec 16 17:16:02 2013 +0100
   115.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   115.3 @@ -1,113 +0,0 @@
   115.4 -/**
   115.5 - * HTML via Java(tm) Language Bindings
   115.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   115.7 - *
   115.8 - * This program is free software: you can redistribute it and/or modify
   115.9 - * it under the terms of the GNU General Public License as published by
  115.10 - * the Free Software Foundation, version 2 of the License.
  115.11 - *
  115.12 - * This program is distributed in the hope that it will be useful,
  115.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  115.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  115.15 - * GNU General Public License for more details. apidesign.org
  115.16 - * designates this particular file as subject to the
  115.17 - * "Classpath" exception as provided by apidesign.org
  115.18 - * in the License file that accompanied this code.
  115.19 - *
  115.20 - * You should have received a copy of the GNU General Public License
  115.21 - * along with this program. Look for COPYING file in the top folder.
  115.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  115.23 - */
  115.24 -package org.apidesign.html.json.impl;
  115.25 -
  115.26 -import net.java.html.BrwsrCtx;
  115.27 -import org.apidesign.html.json.spi.FunctionBinding;
  115.28 -import org.apidesign.html.json.spi.JSONCall;
  115.29 -import org.apidesign.html.json.spi.PropertyBinding;
  115.30 -
  115.31 -/**
  115.32 - *
  115.33 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  115.34 - */
  115.35 -public abstract class PropertyBindingAccessor {
  115.36 -    private static PropertyBindingAccessor DEFAULT;
  115.37 -
  115.38 -    protected PropertyBindingAccessor() {
  115.39 -        if (DEFAULT != null) throw new IllegalStateException();
  115.40 -        DEFAULT = this;
  115.41 -    }
  115.42 -    
  115.43 -    static {
  115.44 -        JSON.initClass(PropertyBinding.class);
  115.45 -    }
  115.46 -
  115.47 -    protected abstract <M> PropertyBinding newBinding(PBData<M> d);
  115.48 -    protected abstract <M> FunctionBinding newFunction(FBData<M> d);
  115.49 -    protected abstract JSONCall newCall(
  115.50 -        BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter,
  115.51 -        String method, Object data
  115.52 -    );
  115.53 -
  115.54 -    
  115.55 -    static <M> PropertyBinding create(PBData<M> d) {
  115.56 -        return DEFAULT.newBinding(d);
  115.57 -    }
  115.58 -    static <M> FunctionBinding createFunction(FBData<M> d) {
  115.59 -        return DEFAULT.newFunction(d);
  115.60 -    }
  115.61 -    static JSONCall createCall(
  115.62 -        BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter, 
  115.63 -        String method, Object data
  115.64 -    ) {
  115.65 -        return DEFAULT.newCall(ctx, callback, urlBefore, urlAfter, method, data);
  115.66 -    }
  115.67 -
  115.68 -    public static final class PBData<M> {
  115.69 -        public final String name;
  115.70 -        public final boolean readOnly;
  115.71 -        private final M model;
  115.72 -        private final SetAndGet<M> access;
  115.73 -        private final Bindings<?> bindings;
  115.74 -
  115.75 -        public PBData(Bindings<?> bindings, String name, M model, SetAndGet<M> access, boolean readOnly) {
  115.76 -            this.bindings = bindings;
  115.77 -            this.name = name;
  115.78 -            this.model = model;
  115.79 -            this.access = access;
  115.80 -            this.readOnly = readOnly;
  115.81 -        }
  115.82 -
  115.83 -        public void setValue(Object v) {
  115.84 -            access.setValue(model, v);
  115.85 -        }
  115.86 -
  115.87 -        public Object getValue() {
  115.88 -            return access.getValue(model);
  115.89 -        }
  115.90 -
  115.91 -        public boolean isReadOnly() {
  115.92 -            return readOnly;
  115.93 -        }
  115.94 -
  115.95 -        public Bindings getBindings() {
  115.96 -            return bindings;
  115.97 -        }
  115.98 -    } // end of PBData
  115.99 -    
 115.100 -    public static final class FBData<M> {
 115.101 -        public final String name;
 115.102 -        private final M model;
 115.103 -        private final Callback<M> access;
 115.104 -
 115.105 -        public FBData(String name, M model, Callback<M> access) {
 115.106 -            this.name = name;
 115.107 -            this.model = model;
 115.108 -            this.access = access;
 115.109 -        }
 115.110 -
 115.111 -
 115.112 -        public void call(Object data, Object ev) {
 115.113 -            access.call(model, data, ev);
 115.114 -        }
 115.115 -    } // end of FBData
 115.116 -}
   116.1 --- a/json/src/main/java/org/apidesign/html/json/impl/RcvrJSON.java	Mon Dec 16 17:16:02 2013 +0100
   116.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   116.3 @@ -1,127 +0,0 @@
   116.4 -/**
   116.5 - * HTML via Java(tm) Language Bindings
   116.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   116.7 - *
   116.8 - * This program is free software: you can redistribute it and/or modify
   116.9 - * it under the terms of the GNU General Public License as published by
  116.10 - * the Free Software Foundation, version 2 of the License.
  116.11 - *
  116.12 - * This program is distributed in the hope that it will be useful,
  116.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  116.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  116.15 - * GNU General Public License for more details. apidesign.org
  116.16 - * designates this particular file as subject to the
  116.17 - * "Classpath" exception as provided by apidesign.org
  116.18 - * in the License file that accompanied this code.
  116.19 - *
  116.20 - * You should have received a copy of the GNU General Public License
  116.21 - * along with this program. Look for COPYING file in the top folder.
  116.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  116.23 - */
  116.24 -package org.apidesign.html.json.impl;
  116.25 -
  116.26 -import net.java.html.BrwsrCtx;
  116.27 -
  116.28 -/** Super type for those who wish to receive JSON messages.
  116.29 - *
  116.30 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  116.31 - */
  116.32 -public abstract class RcvrJSON {
  116.33 -    protected void onOpen(MsgEvnt msg) {}
  116.34 -    protected abstract void onMessage(MsgEvnt msg);
  116.35 -    protected void onClose(MsgEvnt msg) {}
  116.36 -    protected abstract void onError(MsgEvnt msg);
  116.37 -    
  116.38 -    public abstract static class MsgEvnt {
  116.39 -        MsgEvnt() {
  116.40 -        }
  116.41 -        
  116.42 -        public Throwable getError() {
  116.43 -            return null;
  116.44 -        }
  116.45 -        
  116.46 -        public final Exception getException() {
  116.47 -            Throwable t = getError();
  116.48 -            if (t instanceof Exception) {
  116.49 -                return (Exception)t;
  116.50 -            }
  116.51 -            if (t == null) {
  116.52 -                return null;
  116.53 -            }
  116.54 -            return new Exception(t);
  116.55 -        }
  116.56 -        
  116.57 -        public int dataSize() {
  116.58 -            return -1;
  116.59 -        }
  116.60 -        
  116.61 -        public <Data> void dataRead(BrwsrCtx ctx, Class<? extends Data> type, Data[] fillTheArray) {
  116.62 -        }
  116.63 -
  116.64 -        public abstract void dispatch(RcvrJSON r);
  116.65 -        
  116.66 -        public static MsgEvnt createError(final Throwable t) {
  116.67 -            return new MsgEvnt() {
  116.68 -                @Override
  116.69 -                public Throwable getError() {
  116.70 -                    return t;
  116.71 -                }
  116.72 -
  116.73 -                @Override
  116.74 -                public void dispatch(RcvrJSON r) {
  116.75 -                    r.onError(this);
  116.76 -                }
  116.77 -            };
  116.78 -        }
  116.79 -        
  116.80 -        public static MsgEvnt createMessage(final Object value) {
  116.81 -            return new MsgEvnt() {
  116.82 -                @Override
  116.83 -                public int dataSize() {
  116.84 -                    if (value instanceof Object[]) {
  116.85 -                        return ((Object[])value).length;
  116.86 -                    } else {
  116.87 -                        return 1;
  116.88 -                    }
  116.89 -                }
  116.90 -                
  116.91 -                @Override
  116.92 -                public <Data> void dataRead(BrwsrCtx context, Class<? extends Data> type, Data[] arr) {
  116.93 -                    if (value instanceof Object[]) {
  116.94 -                        Object[] data = ((Object[]) value);
  116.95 -                        for (int i = 0; i < data.length && i < arr.length; i++) {
  116.96 -                            arr[i] = org.apidesign.html.json.impl.JSON.read(context, type, data[i]);
  116.97 -                        }
  116.98 -                    } else {
  116.99 -                        if (arr.length > 0) {
 116.100 -                            arr[0] = org.apidesign.html.json.impl.JSON.read(context, type, value);
 116.101 -                        }
 116.102 -                    }
 116.103 -                }
 116.104 -                
 116.105 -                @Override
 116.106 -                public void dispatch(RcvrJSON r) {
 116.107 -                    r.onMessage(this);
 116.108 -                }
 116.109 -            };
 116.110 -        }
 116.111 -        
 116.112 -        public static MsgEvnt createOpen() {
 116.113 -            return new MsgEvnt() {
 116.114 -                @Override
 116.115 -                public void dispatch(RcvrJSON r) {
 116.116 -                    r.onOpen(this);
 116.117 -                }
 116.118 -            };
 116.119 -        }
 116.120 -
 116.121 -        public static MsgEvnt createClose() {
 116.122 -            return new MsgEvnt() {
 116.123 -                @Override
 116.124 -                public void dispatch(RcvrJSON r) {
 116.125 -                    r.onClose(this);
 116.126 -                }
 116.127 -            };
 116.128 -        }
 116.129 -    } // end MsgEvnt
 116.130 -}
   117.1 --- a/json/src/main/java/org/apidesign/html/json/impl/SetAndGet.java	Mon Dec 16 17:16:02 2013 +0100
   117.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   117.3 @@ -1,33 +0,0 @@
   117.4 -/**
   117.5 - * HTML via Java(tm) Language Bindings
   117.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   117.7 - *
   117.8 - * This program is free software: you can redistribute it and/or modify
   117.9 - * it under the terms of the GNU General Public License as published by
  117.10 - * the Free Software Foundation, version 2 of the License.
  117.11 - *
  117.12 - * This program is distributed in the hope that it will be useful,
  117.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  117.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  117.15 - * GNU General Public License for more details. apidesign.org
  117.16 - * designates this particular file as subject to the
  117.17 - * "Classpath" exception as provided by apidesign.org
  117.18 - * in the License file that accompanied this code.
  117.19 - *
  117.20 - * You should have received a copy of the GNU General Public License
  117.21 - * along with this program. Look for COPYING file in the top folder.
  117.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  117.23 - */
  117.24 -
  117.25 -package org.apidesign.html.json.impl;
  117.26 -
  117.27 -import org.apidesign.html.json.spi.PropertyBinding;
  117.28 -
  117.29 -/** A way to implement a {@link PropertyBinding}.
  117.30 - *
  117.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  117.32 - */
  117.33 -public interface SetAndGet<Data> {
  117.34 -    public void setValue(Data data, Object value);
  117.35 -    public Object getValue(Data data);
  117.36 -}
   118.1 --- a/json/src/main/java/org/apidesign/html/json/impl/WrapperObject.java	Mon Dec 16 17:16:02 2013 +0100
   118.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   118.3 @@ -1,61 +0,0 @@
   118.4 -/**
   118.5 - * HTML via Java(tm) Language Bindings
   118.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   118.7 - *
   118.8 - * This program is free software: you can redistribute it and/or modify
   118.9 - * it under the terms of the GNU General Public License as published by
  118.10 - * the Free Software Foundation, version 2 of the License.
  118.11 - *
  118.12 - * This program is distributed in the hope that it will be useful,
  118.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  118.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  118.15 - * GNU General Public License for more details. apidesign.org
  118.16 - * designates this particular file as subject to the
  118.17 - * "Classpath" exception as provided by apidesign.org
  118.18 - * in the License file that accompanied this code.
  118.19 - *
  118.20 - * You should have received a copy of the GNU General Public License
  118.21 - * along with this program. Look for COPYING file in the top folder.
  118.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  118.23 - */
  118.24 -
  118.25 -package org.apidesign.html.json.impl;
  118.26 -
  118.27 -import java.util.Collection;
  118.28 -import org.apidesign.html.json.impl.PropertyBindingAccessor.PBData;
  118.29 -
  118.30 -/** A way to extract real object from a model classes.
  118.31 - *
  118.32 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  118.33 - */
  118.34 -public final class WrapperObject {
  118.35 -    private Object ko;
  118.36 -    
  118.37 -    private WrapperObject() {
  118.38 -    }
  118.39 -    
  118.40 -    public void setRealObject(Object ko) {
  118.41 -        this.ko = ko;
  118.42 -    }
  118.43 -    
  118.44 -    public static Object find(Object object) {
  118.45 -        return find(object, null);
  118.46 -    }
  118.47 -    
  118.48 -    public static Object find(Object object, Bindings model) {
  118.49 -        if (object == null) {
  118.50 -            return null;
  118.51 -        }
  118.52 -        
  118.53 -        if (object instanceof JSONList) {
  118.54 -            return ((JSONList<?>)object).koData();
  118.55 -        }
  118.56 -        if (object instanceof Collection) {
  118.57 -            return JSONList.koData((Collection<?>)object, model);
  118.58 -        }
  118.59 -        
  118.60 -        WrapperObject ro = new WrapperObject();
  118.61 -        object.equals(ro);
  118.62 -        return ro.ko;
  118.63 -    }
  118.64 -}
   119.1 --- a/json/src/main/java/org/apidesign/html/json/spi/FunctionBinding.java	Mon Dec 16 17:16:02 2013 +0100
   119.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/FunctionBinding.java	Mon Dec 16 17:16:40 2013 +0100
   119.3 @@ -1,28 +1,50 @@
   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 1997-2010 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 org.apidesign.html.json.spi;
  119.62  
  119.63  import net.java.html.json.Function;
  119.64  import net.java.html.json.Model;
  119.65 -import org.apidesign.html.json.impl.PropertyBindingAccessor.FBData;
  119.66 +import org.netbeans.html.json.impl.PropertyBindingAccessor.FBData;
  119.67  
  119.68  /** Describes a function provided by the {@link Model} and 
  119.69   * annotated by {@link Function} annotation.
   120.1 --- a/json/src/main/java/org/apidesign/html/json/spi/JSONCall.java	Mon Dec 16 17:16:02 2013 +0100
   120.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/JSONCall.java	Mon Dec 16 17:16:40 2013 +0100
   120.3 @@ -1,31 +1,52 @@
   120.4  /**
   120.5 - * HTML via Java(tm) Language Bindings
   120.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   120.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   120.8   *
   120.9 - * This program is free software: you can redistribute it and/or modify
  120.10 - * it under the terms of the GNU General Public License as published by
  120.11 - * the Free Software Foundation, version 2 of the License.
  120.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  120.13   *
  120.14 - * This program is distributed in the hope that it will be useful,
  120.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  120.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  120.17 - * GNU General Public License for more details. apidesign.org
  120.18 - * designates this particular file as subject to the
  120.19 - * "Classpath" exception as provided by apidesign.org
  120.20 - * in the License file that accompanied this code.
  120.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  120.22 + * Other names may be trademarks of their respective owners.
  120.23   *
  120.24 - * You should have received a copy of the GNU General Public License
  120.25 - * along with this program. Look for COPYING file in the top folder.
  120.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  120.27 + * The contents of this file are subject to the terms of either the GNU
  120.28 + * General Public License Version 2 only ("GPL") or the Common
  120.29 + * Development and Distribution License("CDDL") (collectively, the
  120.30 + * "License"). You may not use this file except in compliance with the
  120.31 + * License. You can obtain a copy of the License at
  120.32 + * http://www.netbeans.org/cddl-gplv2.html
  120.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  120.34 + * specific language governing permissions and limitations under the
  120.35 + * License.  When distributing the software, include this License Header
  120.36 + * Notice in each file and include the License file at
  120.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  120.38 + * particular file as subject to the "Classpath" exception as provided
  120.39 + * by Oracle in the GPL Version 2 section of the License file that
  120.40 + * accompanied this code. If applicable, add the following below the
  120.41 + * License Header, with the fields enclosed by brackets [] replaced by
  120.42 + * your own identifying information:
  120.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  120.44 + *
  120.45 + * Contributor(s):
  120.46 + *
  120.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  120.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  120.49 + *
  120.50 + * If you wish your version of this file to be governed by only the CDDL
  120.51 + * or only the GPL Version 2, indicate your decision by adding
  120.52 + * "[Contributor] elects to include this software in this distribution
  120.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  120.54 + * single choice of license, a recipient has the option to distribute
  120.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  120.56 + * to extend the choice of license to its licensees as provided above.
  120.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  120.58 + * Version 2 license, then the option applies only if the new code is
  120.59 + * made subject to such option by the copyright holder.
  120.60   */
  120.61 -
  120.62  package org.apidesign.html.json.spi;
  120.63  
  120.64  import java.io.IOException;
  120.65  import java.io.OutputStream;
  120.66  import net.java.html.BrwsrCtx;
  120.67 -import org.apidesign.html.json.impl.JSON;
  120.68 -import org.apidesign.html.json.impl.RcvrJSON;
  120.69 +import org.netbeans.html.json.impl.JSON;
  120.70 +import org.netbeans.html.json.impl.RcvrJSON;
  120.71  
  120.72  /** Description of a JSON call request that is supposed to be processed
  120.73   * by {@link Transfer#loadJSON(org.apidesign.html.json.spi.JSONCall)} implementors.
   121.1 --- a/json/src/main/java/org/apidesign/html/json/spi/PropertyBinding.java	Mon Dec 16 17:16:02 2013 +0100
   121.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/PropertyBinding.java	Mon Dec 16 17:16:40 2013 +0100
   121.3 @@ -1,30 +1,52 @@
   121.4  /**
   121.5 - * HTML via Java(tm) Language Bindings
   121.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   121.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   121.8   *
   121.9 - * This program is free software: you can redistribute it and/or modify
  121.10 - * it under the terms of the GNU General Public License as published by
  121.11 - * the Free Software Foundation, version 2 of the License.
  121.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  121.13   *
  121.14 - * This program is distributed in the hope that it will be useful,
  121.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  121.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  121.17 - * GNU General Public License for more details. apidesign.org
  121.18 - * designates this particular file as subject to the
  121.19 - * "Classpath" exception as provided by apidesign.org
  121.20 - * in the License file that accompanied this code.
  121.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  121.22 + * Other names may be trademarks of their respective owners.
  121.23   *
  121.24 - * You should have received a copy of the GNU General Public License
  121.25 - * along with this program. Look for COPYING file in the top folder.
  121.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  121.27 + * The contents of this file are subject to the terms of either the GNU
  121.28 + * General Public License Version 2 only ("GPL") or the Common
  121.29 + * Development and Distribution License("CDDL") (collectively, the
  121.30 + * "License"). You may not use this file except in compliance with the
  121.31 + * License. You can obtain a copy of the License at
  121.32 + * http://www.netbeans.org/cddl-gplv2.html
  121.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  121.34 + * specific language governing permissions and limitations under the
  121.35 + * License.  When distributing the software, include this License Header
  121.36 + * Notice in each file and include the License file at
  121.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  121.38 + * particular file as subject to the "Classpath" exception as provided
  121.39 + * by Oracle in the GPL Version 2 section of the License file that
  121.40 + * accompanied this code. If applicable, add the following below the
  121.41 + * License Header, with the fields enclosed by brackets [] replaced by
  121.42 + * your own identifying information:
  121.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  121.44 + *
  121.45 + * Contributor(s):
  121.46 + *
  121.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  121.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  121.49 + *
  121.50 + * If you wish your version of this file to be governed by only the CDDL
  121.51 + * or only the GPL Version 2, indicate your decision by adding
  121.52 + * "[Contributor] elects to include this software in this distribution
  121.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  121.54 + * single choice of license, a recipient has the option to distribute
  121.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  121.56 + * to extend the choice of license to its licensees as provided above.
  121.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  121.58 + * Version 2 license, then the option applies only if the new code is
  121.59 + * made subject to such option by the copyright holder.
  121.60   */
  121.61  package org.apidesign.html.json.spi;
  121.62  
  121.63  import net.java.html.BrwsrCtx;
  121.64 -import org.apidesign.html.json.impl.PropertyBindingAccessor;
  121.65 -import org.apidesign.html.json.impl.PropertyBindingAccessor.PBData;
  121.66 -import org.apidesign.html.json.impl.RcvrJSON;
  121.67 -import org.apidesign.html.json.impl.WrapperObject;
  121.68 +import org.netbeans.html.json.impl.PropertyBindingAccessor;
  121.69 +import org.netbeans.html.json.impl.PropertyBindingAccessor.PBData;
  121.70 +import org.netbeans.html.json.impl.RcvrJSON;
  121.71 +import org.netbeans.html.json.impl.WrapperObject;
  121.72  
  121.73  /** Describes a property when one is asked to 
  121.74   * bind it 
   122.1 --- a/json/src/main/java/org/apidesign/html/json/spi/Technology.java	Mon Dec 16 17:16:02 2013 +0100
   122.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/Technology.java	Mon Dec 16 17:16:40 2013 +0100
   122.3 @@ -1,22 +1,44 @@
   122.4  /**
   122.5 - * HTML via Java(tm) Language Bindings
   122.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   122.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   122.8   *
   122.9 - * This program is free software: you can redistribute it and/or modify
  122.10 - * it under the terms of the GNU General Public License as published by
  122.11 - * the Free Software Foundation, version 2 of the License.
  122.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  122.13   *
  122.14 - * This program is distributed in the hope that it will be useful,
  122.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  122.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  122.17 - * GNU General Public License for more details. apidesign.org
  122.18 - * designates this particular file as subject to the
  122.19 - * "Classpath" exception as provided by apidesign.org
  122.20 - * in the License file that accompanied this code.
  122.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  122.22 + * Other names may be trademarks of their respective owners.
  122.23   *
  122.24 - * You should have received a copy of the GNU General Public License
  122.25 - * along with this program. Look for COPYING file in the top folder.
  122.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  122.27 + * The contents of this file are subject to the terms of either the GNU
  122.28 + * General Public License Version 2 only ("GPL") or the Common
  122.29 + * Development and Distribution License("CDDL") (collectively, the
  122.30 + * "License"). You may not use this file except in compliance with the
  122.31 + * License. You can obtain a copy of the License at
  122.32 + * http://www.netbeans.org/cddl-gplv2.html
  122.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  122.34 + * specific language governing permissions and limitations under the
  122.35 + * License.  When distributing the software, include this License Header
  122.36 + * Notice in each file and include the License file at
  122.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  122.38 + * particular file as subject to the "Classpath" exception as provided
  122.39 + * by Oracle in the GPL Version 2 section of the License file that
  122.40 + * accompanied this code. If applicable, add the following below the
  122.41 + * License Header, with the fields enclosed by brackets [] replaced by
  122.42 + * your own identifying information:
  122.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  122.44 + *
  122.45 + * Contributor(s):
  122.46 + *
  122.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  122.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  122.49 + *
  122.50 + * If you wish your version of this file to be governed by only the CDDL
  122.51 + * or only the GPL Version 2, indicate your decision by adding
  122.52 + * "[Contributor] elects to include this software in this distribution
  122.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  122.54 + * single choice of license, a recipient has the option to distribute
  122.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  122.56 + * to extend the choice of license to its licensees as provided above.
  122.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  122.58 + * Version 2 license, then the option applies only if the new code is
  122.59 + * made subject to such option by the copyright holder.
  122.60   */
  122.61  package org.apidesign.html.json.spi;
  122.62  
   123.1 --- a/json/src/main/java/org/apidesign/html/json/spi/Transfer.java	Mon Dec 16 17:16:02 2013 +0100
   123.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/Transfer.java	Mon Dec 16 17:16:40 2013 +0100
   123.3 @@ -1,24 +1,45 @@
   123.4  /**
   123.5 - * HTML via Java(tm) Language Bindings
   123.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   123.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   123.8   *
   123.9 - * This program is free software: you can redistribute it and/or modify
  123.10 - * it under the terms of the GNU General Public License as published by
  123.11 - * the Free Software Foundation, version 2 of the License.
  123.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  123.13   *
  123.14 - * This program is distributed in the hope that it will be useful,
  123.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  123.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  123.17 - * GNU General Public License for more details. apidesign.org
  123.18 - * designates this particular file as subject to the
  123.19 - * "Classpath" exception as provided by apidesign.org
  123.20 - * in the License file that accompanied this code.
  123.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  123.22 + * Other names may be trademarks of their respective owners.
  123.23   *
  123.24 - * You should have received a copy of the GNU General Public License
  123.25 - * along with this program. Look for COPYING file in the top folder.
  123.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  123.27 + * The contents of this file are subject to the terms of either the GNU
  123.28 + * General Public License Version 2 only ("GPL") or the Common
  123.29 + * Development and Distribution License("CDDL") (collectively, the
  123.30 + * "License"). You may not use this file except in compliance with the
  123.31 + * License. You can obtain a copy of the License at
  123.32 + * http://www.netbeans.org/cddl-gplv2.html
  123.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  123.34 + * specific language governing permissions and limitations under the
  123.35 + * License.  When distributing the software, include this License Header
  123.36 + * Notice in each file and include the License file at
  123.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  123.38 + * particular file as subject to the "Classpath" exception as provided
  123.39 + * by Oracle in the GPL Version 2 section of the License file that
  123.40 + * accompanied this code. If applicable, add the following below the
  123.41 + * License Header, with the fields enclosed by brackets [] replaced by
  123.42 + * your own identifying information:
  123.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  123.44 + *
  123.45 + * Contributor(s):
  123.46 + *
  123.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  123.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  123.49 + *
  123.50 + * If you wish your version of this file to be governed by only the CDDL
  123.51 + * or only the GPL Version 2, indicate your decision by adding
  123.52 + * "[Contributor] elects to include this software in this distribution
  123.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  123.54 + * single choice of license, a recipient has the option to distribute
  123.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  123.56 + * to extend the choice of license to its licensees as provided above.
  123.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  123.58 + * Version 2 license, then the option applies only if the new code is
  123.59 + * made subject to such option by the copyright holder.
  123.60   */
  123.61 -
  123.62  package org.apidesign.html.json.spi;
  123.63  
  123.64  import java.io.IOException;
   124.1 --- a/json/src/main/java/org/apidesign/html/json/spi/WSTransfer.java	Mon Dec 16 17:16:02 2013 +0100
   124.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/WSTransfer.java	Mon Dec 16 17:16:40 2013 +0100
   124.3 @@ -1,22 +1,44 @@
   124.4  /**
   124.5 - * HTML via Java(tm) Language Bindings
   124.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   124.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   124.8   *
   124.9 - * This program is free software: you can redistribute it and/or modify
  124.10 - * it under the terms of the GNU General Public License as published by
  124.11 - * the Free Software Foundation, version 2 of the License.
  124.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  124.13   *
  124.14 - * This program is distributed in the hope that it will be useful,
  124.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  124.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  124.17 - * GNU General Public License for more details. apidesign.org
  124.18 - * designates this particular file as subject to the
  124.19 - * "Classpath" exception as provided by apidesign.org
  124.20 - * in the License file that accompanied this code.
  124.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  124.22 + * Other names may be trademarks of their respective owners.
  124.23   *
  124.24 - * You should have received a copy of the GNU General Public License
  124.25 - * along with this program. Look for COPYING file in the top folder.
  124.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  124.27 + * The contents of this file are subject to the terms of either the GNU
  124.28 + * General Public License Version 2 only ("GPL") or the Common
  124.29 + * Development and Distribution License("CDDL") (collectively, the
  124.30 + * "License"). You may not use this file except in compliance with the
  124.31 + * License. You can obtain a copy of the License at
  124.32 + * http://www.netbeans.org/cddl-gplv2.html
  124.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  124.34 + * specific language governing permissions and limitations under the
  124.35 + * License.  When distributing the software, include this License Header
  124.36 + * Notice in each file and include the License file at
  124.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  124.38 + * particular file as subject to the "Classpath" exception as provided
  124.39 + * by Oracle in the GPL Version 2 section of the License file that
  124.40 + * accompanied this code. If applicable, add the following below the
  124.41 + * License Header, with the fields enclosed by brackets [] replaced by
  124.42 + * your own identifying information:
  124.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  124.44 + *
  124.45 + * Contributor(s):
  124.46 + *
  124.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  124.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  124.49 + *
  124.50 + * If you wish your version of this file to be governed by only the CDDL
  124.51 + * or only the GPL Version 2, indicate your decision by adding
  124.52 + * "[Contributor] elects to include this software in this distribution
  124.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  124.54 + * single choice of license, a recipient has the option to distribute
  124.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  124.56 + * to extend the choice of license to its licensees as provided above.
  124.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  124.58 + * Version 2 license, then the option applies only if the new code is
  124.59 + * made subject to such option by the copyright holder.
  124.60   */
  124.61  package org.apidesign.html.json.spi;
  124.62  
   125.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   125.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/Bindings.java	Mon Dec 16 17:16:40 2013 +0100
   125.3 @@ -0,0 +1,113 @@
   125.4 +/**
   125.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   125.6 + *
   125.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   125.8 + *
   125.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  125.10 + * Other names may be trademarks of their respective owners.
  125.11 + *
  125.12 + * The contents of this file are subject to the terms of either the GNU
  125.13 + * General Public License Version 2 only ("GPL") or the Common
  125.14 + * Development and Distribution License("CDDL") (collectively, the
  125.15 + * "License"). You may not use this file except in compliance with the
  125.16 + * License. You can obtain a copy of the License at
  125.17 + * http://www.netbeans.org/cddl-gplv2.html
  125.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  125.19 + * specific language governing permissions and limitations under the
  125.20 + * License.  When distributing the software, include this License Header
  125.21 + * Notice in each file and include the License file at
  125.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  125.23 + * particular file as subject to the "Classpath" exception as provided
  125.24 + * by Oracle in the GPL Version 2 section of the License file that
  125.25 + * accompanied this code. If applicable, add the following below the
  125.26 + * License Header, with the fields enclosed by brackets [] replaced by
  125.27 + * your own identifying information:
  125.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  125.29 + *
  125.30 + * Contributor(s):
  125.31 + *
  125.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  125.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  125.34 + *
  125.35 + * If you wish your version of this file to be governed by only the CDDL
  125.36 + * or only the GPL Version 2, indicate your decision by adding
  125.37 + * "[Contributor] elects to include this software in this distribution
  125.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  125.39 + * single choice of license, a recipient has the option to distribute
  125.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  125.41 + * to extend the choice of license to its licensees as provided above.
  125.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  125.43 + * Version 2 license, then the option applies only if the new code is
  125.44 + * made subject to such option by the copyright holder.
  125.45 + */
  125.46 +package org.netbeans.html.json.impl;
  125.47 +
  125.48 +import org.apidesign.html.json.spi.PropertyBinding;
  125.49 +import net.java.html.BrwsrCtx;
  125.50 +import org.netbeans.html.json.impl.PropertyBindingAccessor.FBData;
  125.51 +import org.netbeans.html.json.impl.PropertyBindingAccessor.PBData;
  125.52 +import org.apidesign.html.json.spi.FunctionBinding;
  125.53 +import org.apidesign.html.json.spi.Technology;
  125.54 +
  125.55 +/**
  125.56 + *
  125.57 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  125.58 + */
  125.59 +public final class Bindings<Data> {
  125.60 +    private Data data;
  125.61 +    private final Technology<Data> bp;
  125.62 +
  125.63 +    private Bindings(Technology<Data> bp) {
  125.64 +        this.bp = bp;
  125.65 +    }
  125.66 +    
  125.67 +    public <M> PropertyBinding registerProperty(String propName, M model, SetAndGet<M> access, boolean readOnly) {
  125.68 +        return PropertyBindingAccessor.create(new PBData<M>(this, propName, model, access, readOnly));
  125.69 +    }
  125.70 +
  125.71 +    public <M> FunctionBinding registerFunction(String name, M model, Callback<M> access) {
  125.72 +        return PropertyBindingAccessor.createFunction(new FBData<M>(name, model, access));
  125.73 +    }
  125.74 +    
  125.75 +    public static Bindings<?> apply(BrwsrCtx c, Object model) {
  125.76 +        Technology<?> bp = JSON.findTechnology(c);
  125.77 +        return apply(bp);
  125.78 +    }
  125.79 +    
  125.80 +    private static <Data> Bindings<Data> apply(Technology<Data> bp) {
  125.81 +        return new Bindings<Data>(bp);
  125.82 +    }
  125.83 +    
  125.84 +    public final void finish(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
  125.85 +        assert data == null;
  125.86 +        if (bp instanceof Technology.BatchInit) {
  125.87 +            Technology.BatchInit<Data> bi = (Technology.BatchInit<Data>)bp;
  125.88 +            data = bi.wrapModel(model, propArr, funcArr);
  125.89 +        } else {
  125.90 +            data = bp.wrapModel(model);
  125.91 +            for (PropertyBinding b : propArr) {
  125.92 +                bp.bind(b, model, data);
  125.93 +            }
  125.94 +            for (FunctionBinding b : funcArr) {
  125.95 +                bp.expose(b, model, data);
  125.96 +            }
  125.97 +        }
  125.98 +    }
  125.99 +    
 125.100 +    
 125.101 +    public Data koData() {
 125.102 +        return data;
 125.103 +    }
 125.104 +
 125.105 +    public void valueHasMutated(String firstName) {
 125.106 +        bp.valueHasMutated(data, firstName);
 125.107 +    }
 125.108 +    
 125.109 +    public void applyBindings() {
 125.110 +        bp.applyBindings(data);
 125.111 +    }
 125.112 +
 125.113 +    Object wrapArray(Object[] arr) {
 125.114 +        return bp.wrapArray(arr);
 125.115 +    }
 125.116 +}
   126.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   126.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/Callback.java	Mon Dec 16 17:16:40 2013 +0100
   126.3 @@ -0,0 +1,51 @@
   126.4 +/**
   126.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   126.6 + *
   126.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   126.8 + *
   126.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  126.10 + * Other names may be trademarks of their respective owners.
  126.11 + *
  126.12 + * The contents of this file are subject to the terms of either the GNU
  126.13 + * General Public License Version 2 only ("GPL") or the Common
  126.14 + * Development and Distribution License("CDDL") (collectively, the
  126.15 + * "License"). You may not use this file except in compliance with the
  126.16 + * License. You can obtain a copy of the License at
  126.17 + * http://www.netbeans.org/cddl-gplv2.html
  126.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  126.19 + * specific language governing permissions and limitations under the
  126.20 + * License.  When distributing the software, include this License Header
  126.21 + * Notice in each file and include the License file at
  126.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  126.23 + * particular file as subject to the "Classpath" exception as provided
  126.24 + * by Oracle in the GPL Version 2 section of the License file that
  126.25 + * accompanied this code. If applicable, add the following below the
  126.26 + * License Header, with the fields enclosed by brackets [] replaced by
  126.27 + * your own identifying information:
  126.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  126.29 + *
  126.30 + * Contributor(s):
  126.31 + *
  126.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  126.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  126.34 + *
  126.35 + * If you wish your version of this file to be governed by only the CDDL
  126.36 + * or only the GPL Version 2, indicate your decision by adding
  126.37 + * "[Contributor] elects to include this software in this distribution
  126.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  126.39 + * single choice of license, a recipient has the option to distribute
  126.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  126.41 + * to extend the choice of license to its licensees as provided above.
  126.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  126.43 + * Version 2 license, then the option applies only if the new code is
  126.44 + * made subject to such option by the copyright holder.
  126.45 + */
  126.46 +package org.netbeans.html.json.impl;
  126.47 +
  126.48 +/**
  126.49 + *
  126.50 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  126.51 + */
  126.52 +public interface Callback<Data> {
  126.53 +    public void call(Data model, Object data, Object ev);
  126.54 +}
   127.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   127.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/FromJSON.java	Mon Dec 16 17:16:40 2013 +0100
   127.3 @@ -0,0 +1,55 @@
   127.4 +/**
   127.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   127.6 + *
   127.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   127.8 + *
   127.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  127.10 + * Other names may be trademarks of their respective owners.
  127.11 + *
  127.12 + * The contents of this file are subject to the terms of either the GNU
  127.13 + * General Public License Version 2 only ("GPL") or the Common
  127.14 + * Development and Distribution License("CDDL") (collectively, the
  127.15 + * "License"). You may not use this file except in compliance with the
  127.16 + * License. You can obtain a copy of the License at
  127.17 + * http://www.netbeans.org/cddl-gplv2.html
  127.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  127.19 + * specific language governing permissions and limitations under the
  127.20 + * License.  When distributing the software, include this License Header
  127.21 + * Notice in each file and include the License file at
  127.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  127.23 + * particular file as subject to the "Classpath" exception as provided
  127.24 + * by Oracle in the GPL Version 2 section of the License file that
  127.25 + * accompanied this code. If applicable, add the following below the
  127.26 + * License Header, with the fields enclosed by brackets [] replaced by
  127.27 + * your own identifying information:
  127.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  127.29 + *
  127.30 + * Contributor(s):
  127.31 + *
  127.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  127.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  127.34 + *
  127.35 + * If you wish your version of this file to be governed by only the CDDL
  127.36 + * or only the GPL Version 2, indicate your decision by adding
  127.37 + * "[Contributor] elects to include this software in this distribution
  127.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  127.39 + * single choice of license, a recipient has the option to distribute
  127.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  127.41 + * to extend the choice of license to its licensees as provided above.
  127.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  127.43 + * Version 2 license, then the option applies only if the new code is
  127.44 + * made subject to such option by the copyright holder.
  127.45 + */
  127.46 +package org.netbeans.html.json.impl;
  127.47 +
  127.48 +import net.java.html.BrwsrCtx;
  127.49 +
  127.50 +/**
  127.51 + *
  127.52 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  127.53 + */
  127.54 +public interface FromJSON<Data> {
  127.55 +    public Class<Data> factoryFor();
  127.56 +    public Data read(BrwsrCtx c, Object d);
  127.57 +    public Data cloneTo(Object d, BrwsrCtx c);
  127.58 +}
   128.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   128.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/JSON.java	Mon Dec 16 17:16:40 2013 +0100
   128.3 @@ -0,0 +1,474 @@
   128.4 +/**
   128.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   128.6 + *
   128.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   128.8 + *
   128.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  128.10 + * Other names may be trademarks of their respective owners.
  128.11 + *
  128.12 + * The contents of this file are subject to the terms of either the GNU
  128.13 + * General Public License Version 2 only ("GPL") or the Common
  128.14 + * Development and Distribution License("CDDL") (collectively, the
  128.15 + * "License"). You may not use this file except in compliance with the
  128.16 + * License. You can obtain a copy of the License at
  128.17 + * http://www.netbeans.org/cddl-gplv2.html
  128.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  128.19 + * specific language governing permissions and limitations under the
  128.20 + * License.  When distributing the software, include this License Header
  128.21 + * Notice in each file and include the License file at
  128.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  128.23 + * particular file as subject to the "Classpath" exception as provided
  128.24 + * by Oracle in the GPL Version 2 section of the License file that
  128.25 + * accompanied this code. If applicable, add the following below the
  128.26 + * License Header, with the fields enclosed by brackets [] replaced by
  128.27 + * your own identifying information:
  128.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  128.29 + *
  128.30 + * Contributor(s):
  128.31 + *
  128.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  128.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  128.34 + *
  128.35 + * If you wish your version of this file to be governed by only the CDDL
  128.36 + * or only the GPL Version 2, indicate your decision by adding
  128.37 + * "[Contributor] elects to include this software in this distribution
  128.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  128.39 + * single choice of license, a recipient has the option to distribute
  128.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  128.41 + * to extend the choice of license to its licensees as provided above.
  128.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  128.43 + * Version 2 license, then the option applies only if the new code is
  128.44 + * made subject to such option by the copyright holder.
  128.45 + */
  128.46 +package org.netbeans.html.json.impl;
  128.47 +
  128.48 +import java.io.IOException;
  128.49 +import java.io.InputStream;
  128.50 +import java.util.HashMap;
  128.51 +import java.util.Map;
  128.52 +import net.java.html.BrwsrCtx;
  128.53 +import org.apidesign.html.context.spi.Contexts;
  128.54 +import org.apidesign.html.json.spi.FunctionBinding;
  128.55 +import org.apidesign.html.json.spi.JSONCall;
  128.56 +import org.apidesign.html.json.spi.PropertyBinding;
  128.57 +import org.apidesign.html.json.spi.Technology;
  128.58 +import org.apidesign.html.json.spi.Transfer;
  128.59 +import org.apidesign.html.json.spi.WSTransfer;
  128.60 +
  128.61 +/**
  128.62 + *
  128.63 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  128.64 + */
  128.65 +public final class JSON {
  128.66 +    private JSON() {
  128.67 +    }
  128.68 +
  128.69 +    static Technology<?> findTechnology(BrwsrCtx c) {
  128.70 +        Technology<?> t = Contexts.find(c, Technology.class);
  128.71 +        return t == null ? EmptyTech.EMPTY : t;
  128.72 +    }
  128.73 +
  128.74 +    static Transfer findTransfer(BrwsrCtx c) {
  128.75 +        Transfer t = Contexts.find(c, Transfer.class);
  128.76 +        return t == null ? EmptyTech.EMPTY : t;
  128.77 +    }
  128.78 +
  128.79 +    static WSTransfer<?> findWSTransfer(BrwsrCtx c) {
  128.80 +        WSTransfer<?> t = Contexts.find(c, WSTransfer.class);
  128.81 +        return t == null ? EmptyTech.EMPTY : t;
  128.82 +    }
  128.83 +    
  128.84 +    public static void runInBrowser(BrwsrCtx c, Runnable runnable) {
  128.85 +        findTechnology(c).runSafe(runnable);
  128.86 +    }
  128.87 +    
  128.88 +    public static void extract(BrwsrCtx c, Object value, String[] props, Object[] values) {
  128.89 +        Transfer t = findTransfer(c);
  128.90 +        t.extract(value, props, values);
  128.91 +    }
  128.92 +    
  128.93 +    private static Object getProperty(BrwsrCtx c, Object obj, String prop) {
  128.94 +        if (prop == null) return obj;
  128.95 +        
  128.96 +        String[] arr = { prop };
  128.97 +        Object[] val = { null };
  128.98 +        extract(c, obj, arr, val);
  128.99 +        return val[0];
 128.100 +    }
 128.101 +
 128.102 +    public static Object toJSON(Object value) {
 128.103 +        if (value == null) {
 128.104 +            return "null";
 128.105 +        }
 128.106 +        if (value instanceof Enum) {
 128.107 +            value = value.toString();
 128.108 +        }
 128.109 +        if (value instanceof String) {
 128.110 +            String s = (String)value;
 128.111 +            int len = s.length();
 128.112 +            StringBuilder sb = new StringBuilder(len + 10);
 128.113 +            sb.append('"');
 128.114 +            for (int i = 0; i < len; i++) {
 128.115 +                char ch = s.charAt(i);
 128.116 +                switch (ch) {
 128.117 +                    case '\"': sb.append("\\\""); break;
 128.118 +                    case '\n': sb.append("\\n"); break;
 128.119 +                    case '\r': sb.append("\\r"); break;
 128.120 +                    case '\t': sb.append("\\t"); break;
 128.121 +                    case '\\': sb.append("\\\\"); break;
 128.122 +                    default: sb.append(ch);
 128.123 +                }
 128.124 +            }
 128.125 +            sb.append('"');
 128.126 +            return sb.toString();
 128.127 +        }
 128.128 +        return value.toString();
 128.129 +    }
 128.130 +
 128.131 +    public static String toString(BrwsrCtx c, Object obj, String prop) {
 128.132 +        obj = getProperty(c, obj, prop);
 128.133 +        return obj instanceof String ? (String)obj : null;
 128.134 +    }
 128.135 +    public static Number toNumber(BrwsrCtx c, Object obj, String prop) {
 128.136 +        obj = getProperty(c, obj, prop);
 128.137 +        if (!(obj instanceof Number)) {
 128.138 +            obj = Double.NaN;
 128.139 +        }
 128.140 +        return (Number)obj;
 128.141 +    }
 128.142 +    public static <M> M toModel(BrwsrCtx c, Class<M> aClass, Object data, Object object) {
 128.143 +        Technology<?> t = findTechnology(c);
 128.144 +        Object o = t.toModel(aClass, data);
 128.145 +        return aClass.cast(o);
 128.146 +    }
 128.147 +    
 128.148 +    public static boolean isSame(int a, int b) {
 128.149 +        return a == b;
 128.150 +    }
 128.151 +    
 128.152 +    public static boolean isSame(double a, double b) {
 128.153 +        return a == b;
 128.154 +    }
 128.155 +    
 128.156 +    public static boolean isSame(Object a, Object b) {
 128.157 +        if (a == b) {
 128.158 +            return true;
 128.159 +        }
 128.160 +        if (a == null || b == null) {
 128.161 +            return false;
 128.162 +        }
 128.163 +        return a.equals(b);
 128.164 +    }
 128.165 +    
 128.166 +    public static int hashPlus(Object o, int h) {
 128.167 +        return o == null ? h : h ^ o.hashCode();
 128.168 +    }
 128.169 +
 128.170 +    public static <T> T extractValue(Class<T> type, Object val) {
 128.171 +        if (Number.class.isAssignableFrom(type)) {
 128.172 +            val = numberValue(val);
 128.173 +        }
 128.174 +        if (Boolean.class == type) {
 128.175 +            val = boolValue(val);
 128.176 +        }
 128.177 +        if (String.class == type) {
 128.178 +            val = stringValue(val);
 128.179 +        }
 128.180 +        if (Character.class == type) {
 128.181 +            val = charValue(val);
 128.182 +        }
 128.183 +        if (Integer.class == type) {
 128.184 +            val = val instanceof Number ? ((Number)val).intValue() : 0;
 128.185 +        }
 128.186 +        if (Long.class == type) {
 128.187 +            val = val instanceof Number  ? ((Number)val).longValue() : 0;
 128.188 +        }
 128.189 +        if (Short.class == type) {
 128.190 +            val = val instanceof Number ? ((Number)val).shortValue() : 0;
 128.191 +        }
 128.192 +        if (Byte.class == type) {
 128.193 +            val = val instanceof Number ? ((Number)val).byteValue() : 0;
 128.194 +        }        
 128.195 +        if (Double.class == type) {
 128.196 +            val = val instanceof Number ? ((Number)val).doubleValue() : Double.NaN;
 128.197 +        }
 128.198 +        if (Float.class == type) {
 128.199 +            val = val instanceof Number ? ((Number)val).floatValue() : Float.NaN;
 128.200 +        }
 128.201 +        return type.cast(val);
 128.202 +    }
 128.203 +    
 128.204 +    protected static boolean isNumeric(Object val) {
 128.205 +        return ((val instanceof Integer) || (val instanceof Long) || (val instanceof Short) || (val instanceof Byte));
 128.206 +    }
 128.207 +    
 128.208 +    public static String stringValue(Object val) {
 128.209 +        if (val instanceof Boolean) {
 128.210 +            return ((Boolean)val ? "true" : "false");
 128.211 +        }
 128.212 +        if (isNumeric(val)) {
 128.213 +            return Long.toString(((Number)val).longValue());
 128.214 +        }
 128.215 +        if (val instanceof Float) {
 128.216 +            return Float.toString((Float)val);
 128.217 +        }
 128.218 +        if (val instanceof Double) {
 128.219 +            return Double.toString((Double)val);
 128.220 +        }
 128.221 +        return (String)val;
 128.222 +    }
 128.223 +
 128.224 +    public static Number numberValue(Object val) {
 128.225 +        if (val instanceof String) {
 128.226 +            try {
 128.227 +                return Double.valueOf((String)val);
 128.228 +            } catch (NumberFormatException ex) {
 128.229 +                return Double.NaN;
 128.230 +            }
 128.231 +        }
 128.232 +        if (val instanceof Boolean) {
 128.233 +            return (Boolean)val ? 1 : 0;
 128.234 +        }
 128.235 +        return (Number)val;
 128.236 +    }
 128.237 +
 128.238 +    public static Character charValue(Object val) {
 128.239 +        if (val instanceof Number) {
 128.240 +            return Character.toChars(numberValue(val).intValue())[0];
 128.241 +        }
 128.242 +        if (val instanceof Boolean) {
 128.243 +            return (Boolean)val ? (char)1 : (char)0;
 128.244 +        }
 128.245 +        if (val instanceof String) {
 128.246 +            String s = (String)val;
 128.247 +            return s.isEmpty() ? (char)0 : s.charAt(0);
 128.248 +        }
 128.249 +        return (Character)val;
 128.250 +    }
 128.251 +    
 128.252 +    public static Boolean boolValue(Object val) {
 128.253 +        if (val instanceof String) {
 128.254 +            return Boolean.parseBoolean((String)val);
 128.255 +        }
 128.256 +        if (val instanceof Number) {
 128.257 +            return numberValue(val).doubleValue() != 0.0;
 128.258 +        }
 128.259 +    
 128.260 +        return Boolean.TRUE.equals(val);
 128.261 +    }
 128.262 +    
 128.263 +    public static void loadJSON(
 128.264 +        BrwsrCtx c, RcvrJSON callback,
 128.265 +        String urlBefore, String urlAfter, String method,
 128.266 +        Object data
 128.267 +    ) {
 128.268 +        JSONCall call = PropertyBindingAccessor.createCall(c, callback, urlBefore, urlAfter, method, data);
 128.269 +        Transfer t = findTransfer(c);
 128.270 +        t.loadJSON(call);
 128.271 +    }
 128.272 +    public static WS openWS(
 128.273 +        BrwsrCtx c, RcvrJSON r, String url, Object data
 128.274 +    ) {
 128.275 +        WS ws = WSImpl.create(findWSTransfer(c), r);
 128.276 +        ws.send(c, url, data);
 128.277 +        return ws;
 128.278 +    }
 128.279 +    
 128.280 +    public static abstract class WS {
 128.281 +        private WS() {
 128.282 +        }
 128.283 +        
 128.284 +        public abstract void send(BrwsrCtx ctx, String url, Object model);
 128.285 +    }
 128.286 +    
 128.287 +    private static final class WSImpl<Socket> extends WS {
 128.288 +
 128.289 +        private final WSTransfer<Socket> trans;
 128.290 +        private final RcvrJSON rcvr;
 128.291 +        private Socket socket;
 128.292 +        private String prevURL;
 128.293 +
 128.294 +        private WSImpl(WSTransfer<Socket> trans, RcvrJSON rcvr) {
 128.295 +            this.trans = trans;
 128.296 +            this.rcvr = rcvr;
 128.297 +        }
 128.298 +        
 128.299 +        static <Socket> WS create(WSTransfer<Socket> t, RcvrJSON r) {
 128.300 +            return new WSImpl<Socket>(t, r);
 128.301 +        }
 128.302 +
 128.303 +        @Override
 128.304 +        public void send(BrwsrCtx ctx, String url, Object data) {
 128.305 +            Socket s = socket;
 128.306 +            if (s == null) {
 128.307 +                if (data != null) {
 128.308 +                    throw new IllegalStateException("WebSocket is not opened yet. Call with null data, was: " + data);
 128.309 +                }
 128.310 +                JSONCall call = PropertyBindingAccessor.createCall(ctx, rcvr, url, null, "WebSocket", null);
 128.311 +                socket = trans.open(url, call);
 128.312 +                prevURL = url;
 128.313 +                return;
 128.314 +            }
 128.315 +            if (data == null) {
 128.316 +                trans.close(s);
 128.317 +                socket = null;
 128.318 +                return;
 128.319 +            }
 128.320 +            if (!prevURL.equals(url)) {
 128.321 +                throw new IllegalStateException(
 128.322 +                    "Can't call to different URL " + url + " was: " + prevURL + "!"
 128.323 +                    + " Close the socket by calling it will null data first!"
 128.324 +                );
 128.325 +            }
 128.326 +            JSONCall call = PropertyBindingAccessor.createCall(ctx, rcvr, prevURL, null, "WebSocket", data);
 128.327 +            trans.send(s, call);
 128.328 +        }
 128.329 +        
 128.330 +    }
 128.331 +    
 128.332 +    private static final Map<Class,FromJSON<?>> froms;
 128.333 +    static {
 128.334 +        Map<Class,FromJSON<?>> m = new HashMap<Class,FromJSON<?>>();
 128.335 +        froms = m;
 128.336 +    }
 128.337 +    public static void register(FromJSON<?> from) {
 128.338 +        froms.put(from.factoryFor(), from);
 128.339 +    }
 128.340 +    
 128.341 +    public static boolean isModel(Class<?> clazz) {
 128.342 +        return findFrom(clazz) != null; 
 128.343 +    }
 128.344 +    
 128.345 +    private static FromJSON<?> findFrom(Class<?> clazz) {
 128.346 +        for (int i = 0; i < 2; i++) {
 128.347 +            FromJSON<?> from = froms.get(clazz);
 128.348 +            if (from == null) {
 128.349 +                initClass(clazz);
 128.350 +            } else {
 128.351 +                return from;
 128.352 +            }
 128.353 +        }
 128.354 +        return null;
 128.355 +    }
 128.356 +    
 128.357 +    public static <Model> Model bindTo(Model model, BrwsrCtx c) {
 128.358 +        FromJSON<?> from = findFrom(model.getClass());
 128.359 +        if (from == null) {
 128.360 +            throw new IllegalArgumentException();
 128.361 +        }
 128.362 +        return (Model) from.cloneTo(model, c);
 128.363 +    }
 128.364 +    
 128.365 +    public static <T> T readStream(BrwsrCtx c, Class<T> modelClazz, InputStream data) 
 128.366 +    throws IOException {
 128.367 +        Transfer tr = findTransfer(c);
 128.368 +        return read(c, modelClazz, tr.toJSON((InputStream)data));
 128.369 +    }
 128.370 +    public static <T> T read(BrwsrCtx c, Class<T> modelClazz, Object data) {
 128.371 +        if (data == null) {
 128.372 +            return null;
 128.373 +        }
 128.374 +        if (modelClazz == String.class) {
 128.375 +            return modelClazz.cast(data.toString());
 128.376 +        }
 128.377 +        for (int i = 0; i < 2; i++) {
 128.378 +            FromJSON<?> from = froms.get(modelClazz);
 128.379 +            if (from == null) {
 128.380 +                initClass(modelClazz);
 128.381 +            } else {
 128.382 +                return modelClazz.cast(from.read(c, data));
 128.383 +            }
 128.384 +        }
 128.385 +        throw new NullPointerException();
 128.386 +    }
 128.387 +    static void initClass(Class<?> modelClazz) {
 128.388 +        try {
 128.389 +            // try to resolve the class
 128.390 +            ClassLoader l;
 128.391 +            try {
 128.392 +                l = modelClazz.getClassLoader();
 128.393 +            } catch (SecurityException ex) {
 128.394 +                l = null;
 128.395 +            }
 128.396 +            if (l != null) {
 128.397 +                Class.forName(modelClazz.getName(), true, l);
 128.398 +            }
 128.399 +            modelClazz.newInstance();
 128.400 +        } catch (Exception ex) {
 128.401 +            // ignore and try again
 128.402 +        }
 128.403 +    }
 128.404 +    
 128.405 +    private static final class EmptyTech
 128.406 +    implements Technology<Object>, Transfer, WSTransfer<Void> {
 128.407 +        private static final EmptyTech EMPTY = new EmptyTech();
 128.408 +
 128.409 +        @Override
 128.410 +        public Object wrapModel(Object model) {
 128.411 +            return model;
 128.412 +        }
 128.413 +
 128.414 +        @Override
 128.415 +        public void valueHasMutated(Object data, String propertyName) {
 128.416 +        }
 128.417 +
 128.418 +        @Override
 128.419 +        public void bind(PropertyBinding b, Object model, Object data) {
 128.420 +        }
 128.421 +
 128.422 +        @Override
 128.423 +        public void expose(FunctionBinding fb, Object model, Object d) {
 128.424 +        }
 128.425 +
 128.426 +        @Override
 128.427 +        public void applyBindings(Object data) {
 128.428 +        }
 128.429 +
 128.430 +        @Override
 128.431 +        public Object wrapArray(Object[] arr) {
 128.432 +            return arr;
 128.433 +        }
 128.434 +
 128.435 +        @Override
 128.436 +        public void extract(Object obj, String[] props, Object[] values) {
 128.437 +            for (int i = 0; i < values.length; i++) {
 128.438 +                values[i] = null;
 128.439 +            }
 128.440 +        }
 128.441 +
 128.442 +        @Override
 128.443 +        public void loadJSON(JSONCall call) {
 128.444 +            call.notifyError(new UnsupportedOperationException());
 128.445 +        }
 128.446 +
 128.447 +        @Override
 128.448 +        public <M> M toModel(Class<M> modelClass, Object data) {
 128.449 +            return modelClass.cast(data);
 128.450 +        }
 128.451 +
 128.452 +        @Override
 128.453 +        public Object toJSON(InputStream is) throws IOException {
 128.454 +            throw new IOException("Not supported");
 128.455 +        }
 128.456 +
 128.457 +        @Override
 128.458 +        public synchronized void runSafe(Runnable r) {
 128.459 +            r.run();
 128.460 +        }
 128.461 +
 128.462 +        @Override
 128.463 +        public Void open(String url, JSONCall onReply) {
 128.464 +            onReply.notifyError(new UnsupportedOperationException("WebSockets not supported!"));
 128.465 +            return null;
 128.466 +        }
 128.467 +
 128.468 +        @Override
 128.469 +        public void send(Void socket, JSONCall data) {
 128.470 +        }
 128.471 +
 128.472 +        @Override
 128.473 +        public void close(Void socket) {
 128.474 +        }
 128.475 +    }
 128.476 +    
 128.477 +}
   129.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   129.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/JSONList.java	Mon Dec 16 17:16:40 2013 +0100
   129.3 @@ -0,0 +1,236 @@
   129.4 +/**
   129.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   129.6 + *
   129.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   129.8 + *
   129.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  129.10 + * Other names may be trademarks of their respective owners.
  129.11 + *
  129.12 + * The contents of this file are subject to the terms of either the GNU
  129.13 + * General Public License Version 2 only ("GPL") or the Common
  129.14 + * Development and Distribution License("CDDL") (collectively, the
  129.15 + * "License"). You may not use this file except in compliance with the
  129.16 + * License. You can obtain a copy of the License at
  129.17 + * http://www.netbeans.org/cddl-gplv2.html
  129.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  129.19 + * specific language governing permissions and limitations under the
  129.20 + * License.  When distributing the software, include this License Header
  129.21 + * Notice in each file and include the License file at
  129.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  129.23 + * particular file as subject to the "Classpath" exception as provided
  129.24 + * by Oracle in the GPL Version 2 section of the License file that
  129.25 + * accompanied this code. If applicable, add the following below the
  129.26 + * License Header, with the fields enclosed by brackets [] replaced by
  129.27 + * your own identifying information:
  129.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  129.29 + *
  129.30 + * Contributor(s):
  129.31 + *
  129.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  129.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  129.34 + *
  129.35 + * If you wish your version of this file to be governed by only the CDDL
  129.36 + * or only the GPL Version 2, indicate your decision by adding
  129.37 + * "[Contributor] elects to include this software in this distribution
  129.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  129.39 + * single choice of license, a recipient has the option to distribute
  129.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  129.41 + * to extend the choice of license to its licensees as provided above.
  129.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  129.43 + * Version 2 license, then the option applies only if the new code is
  129.44 + * made subject to such option by the copyright holder.
  129.45 + */
  129.46 +package org.netbeans.html.json.impl;
  129.47 +
  129.48 +import java.lang.reflect.Array;
  129.49 +import java.util.ArrayList;
  129.50 +import java.util.Arrays;
  129.51 +import java.util.Collection;
  129.52 +import java.util.Iterator;
  129.53 +import java.util.List;
  129.54 +import net.java.html.BrwsrCtx;
  129.55 +
  129.56 +/**
  129.57 + *
  129.58 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  129.59 + */
  129.60 +public final class JSONList<T> extends ArrayList<T> {
  129.61 +    private final String name;
  129.62 +    private final String[] deps;
  129.63 +    private Bindings[] model;
  129.64 +    private Runnable onchange;
  129.65 +
  129.66 +    public JSONList(Bindings[] model, String name, String... deps) {
  129.67 +        assert model.length == 1;
  129.68 +        this.model = model;
  129.69 +        this.name = name;
  129.70 +        this.deps = deps;
  129.71 +    }
  129.72 +    
  129.73 +    public void init(T... values) {
  129.74 +        if (values == null || values.length == 0) {
  129.75 +            return;
  129.76 +        }
  129.77 +        if (this.model[0] != null || !isEmpty()) {
  129.78 +            throw new IllegalStateException();
  129.79 +        }
  129.80 +        super.addAll(Arrays.asList(values));
  129.81 +    }
  129.82 +    
  129.83 +    public void init(Object values) {
  129.84 +        int len;
  129.85 +        if (values == null || (len = Array.getLength(values)) == 0) {
  129.86 +            return;
  129.87 +        }
  129.88 +        if (this.model[0] != null || !isEmpty()) {
  129.89 +            throw new IllegalStateException();
  129.90 +        }
  129.91 +        for (int i = 0; i < len; i++) {
  129.92 +            Object data = Array.get(values, i);
  129.93 +            super.add((T)data);
  129.94 +        }
  129.95 +    }
  129.96 +    
  129.97 +    public JSONList<T> onChange(Runnable r) {
  129.98 +        if (this.onchange != null) {
  129.99 +            throw new IllegalStateException();
 129.100 +        }
 129.101 +        this.onchange = r;
 129.102 +        return this;
 129.103 +    }
 129.104 +
 129.105 +    @Override
 129.106 +    public boolean add(T e) {
 129.107 +        boolean ret = super.add(e);
 129.108 +        notifyChange();
 129.109 +        return ret;
 129.110 +    }
 129.111 +
 129.112 +    @Override
 129.113 +    public boolean addAll(Collection<? extends T> c) {
 129.114 +        boolean ret = super.addAll(c);
 129.115 +        notifyChange();
 129.116 +        return ret;
 129.117 +    }
 129.118 +
 129.119 +    @Override
 129.120 +    public boolean addAll(int index, Collection<? extends T> c) {
 129.121 +        boolean ret = super.addAll(index, c);
 129.122 +        notifyChange();
 129.123 +        return ret;
 129.124 +    }
 129.125 +
 129.126 +    @Override
 129.127 +    public boolean remove(Object o) {
 129.128 +        boolean ret = super.remove(o);
 129.129 +        notifyChange();
 129.130 +        return ret;
 129.131 +    }
 129.132 +
 129.133 +    @Override
 129.134 +    public void clear() {
 129.135 +        super.clear();
 129.136 +        notifyChange();
 129.137 +    }
 129.138 +
 129.139 +    @Override
 129.140 +    public boolean removeAll(Collection<?> c) {
 129.141 +        boolean ret = super.removeAll(c);
 129.142 +        notifyChange();
 129.143 +        return ret;
 129.144 +    }
 129.145 +
 129.146 +    @Override
 129.147 +    public boolean retainAll(Collection<?> c) {
 129.148 +        boolean ret = super.retainAll(c);
 129.149 +        notifyChange();
 129.150 +        return ret;
 129.151 +    }
 129.152 +
 129.153 +    @Override
 129.154 +    public T set(int index, T element) {
 129.155 +        T ret = super.set(index, element);
 129.156 +        notifyChange();
 129.157 +        return ret;
 129.158 +    }
 129.159 +
 129.160 +    @Override
 129.161 +    public void add(int index, T element) {
 129.162 +        super.add(index, element);
 129.163 +        notifyChange();
 129.164 +    }
 129.165 +
 129.166 +    @Override
 129.167 +    public T remove(int index) {
 129.168 +        T ret = super.remove(index);
 129.169 +        notifyChange();
 129.170 +        return ret;
 129.171 +    }
 129.172 +
 129.173 +    @Override
 129.174 +    public String toString() {
 129.175 +        Iterator<T> it = iterator();
 129.176 +        if (!it.hasNext()) {
 129.177 +            return "[]";
 129.178 +        }
 129.179 +        String sep = "";
 129.180 +        StringBuilder sb = new StringBuilder();
 129.181 +        sb.append('[');
 129.182 +        while (it.hasNext()) {
 129.183 +            T t = it.next();
 129.184 +            sb.append(sep);
 129.185 +            sb.append(JSON.toJSON(t));
 129.186 +            sep = ",";
 129.187 +        }
 129.188 +        sb.append(']');
 129.189 +        return sb.toString();
 129.190 +    }
 129.191 +
 129.192 +    private void notifyChange() {
 129.193 +        Bindings m = model[0];
 129.194 +        if (m != null) {
 129.195 +            m.valueHasMutated(name);
 129.196 +            for (String dependant : deps) {
 129.197 +                m.valueHasMutated(dependant);
 129.198 +            }
 129.199 +            Runnable r = onchange;
 129.200 +            if (r != null) {
 129.201 +                r.run();
 129.202 +            }
 129.203 +        }
 129.204 +    }
 129.205 +    
 129.206 +    public void cloneAll(BrwsrCtx c, Collection<T> other) {
 129.207 +        Boolean isModel = null;
 129.208 +        for (T t : other) {
 129.209 +            if (isModel == null) {
 129.210 +                isModel = JSON.isModel(t.getClass());
 129.211 +            }
 129.212 +            if (isModel) {
 129.213 +                add(JSON.bindTo(t, c));
 129.214 +            } else {
 129.215 +                add(t);
 129.216 +            }
 129.217 +        }
 129.218 +    }
 129.219 +
 129.220 +    @Override
 129.221 +    public JSONList clone() {
 129.222 +        throw new UnsupportedOperationException();
 129.223 +    }
 129.224 +
 129.225 +    static final Object koData(Collection<?> c, Bindings m) {
 129.226 +        Object[] arr = c.toArray(new Object[c.size()]);
 129.227 +        for (int i = 0; i < arr.length; i++) {
 129.228 +            Object r = WrapperObject.find(arr[i], m);
 129.229 +            if (r != null) {
 129.230 +                arr[i] = r;
 129.231 +            }
 129.232 +        }
 129.233 +        return m.wrapArray(arr);
 129.234 +    }
 129.235 +
 129.236 +    final Object koData() {
 129.237 +        return koData(this, model[0]);
 129.238 +    }
 129.239 +}
   130.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   130.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/ModelProcessor.java	Mon Dec 16 17:16:40 2013 +0100
   130.3 @@ -0,0 +1,1767 @@
   130.4 +/**
   130.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   130.6 + *
   130.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   130.8 + *
   130.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  130.10 + * Other names may be trademarks of their respective owners.
  130.11 + *
  130.12 + * The contents of this file are subject to the terms of either the GNU
  130.13 + * General Public License Version 2 only ("GPL") or the Common
  130.14 + * Development and Distribution License("CDDL") (collectively, the
  130.15 + * "License"). You may not use this file except in compliance with the
  130.16 + * License. You can obtain a copy of the License at
  130.17 + * http://www.netbeans.org/cddl-gplv2.html
  130.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  130.19 + * specific language governing permissions and limitations under the
  130.20 + * License.  When distributing the software, include this License Header
  130.21 + * Notice in each file and include the License file at
  130.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  130.23 + * particular file as subject to the "Classpath" exception as provided
  130.24 + * by Oracle in the GPL Version 2 section of the License file that
  130.25 + * accompanied this code. If applicable, add the following below the
  130.26 + * License Header, with the fields enclosed by brackets [] replaced by
  130.27 + * your own identifying information:
  130.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  130.29 + *
  130.30 + * Contributor(s):
  130.31 + *
  130.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  130.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  130.34 + *
  130.35 + * If you wish your version of this file to be governed by only the CDDL
  130.36 + * or only the GPL Version 2, indicate your decision by adding
  130.37 + * "[Contributor] elects to include this software in this distribution
  130.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  130.39 + * single choice of license, a recipient has the option to distribute
  130.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  130.41 + * to extend the choice of license to its licensees as provided above.
  130.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  130.43 + * Version 2 license, then the option applies only if the new code is
  130.44 + * made subject to such option by the copyright holder.
  130.45 + */
  130.46 +package org.netbeans.html.json.impl;
  130.47 +
  130.48 +import java.io.IOException;
  130.49 +import java.io.OutputStreamWriter;
  130.50 +import java.io.StringWriter;
  130.51 +import java.io.Writer;
  130.52 +import java.lang.annotation.AnnotationTypeMismatchException;
  130.53 +import java.lang.annotation.IncompleteAnnotationException;
  130.54 +import java.lang.reflect.Method;
  130.55 +import java.util.ArrayList;
  130.56 +import java.util.Arrays;
  130.57 +import java.util.Collection;
  130.58 +import java.util.Collections;
  130.59 +import java.util.HashMap;
  130.60 +import java.util.HashSet;
  130.61 +import java.util.LinkedHashSet;
  130.62 +import java.util.List;
  130.63 +import java.util.Map;
  130.64 +import java.util.ResourceBundle;
  130.65 +import java.util.Set;
  130.66 +import java.util.WeakHashMap;
  130.67 +import java.util.logging.Level;
  130.68 +import java.util.logging.Logger;
  130.69 +import javax.annotation.processing.AbstractProcessor;
  130.70 +import javax.annotation.processing.Completion;
  130.71 +import javax.annotation.processing.Completions;
  130.72 +import javax.annotation.processing.ProcessingEnvironment;
  130.73 +import javax.annotation.processing.Processor;
  130.74 +import javax.annotation.processing.RoundEnvironment;
  130.75 +import javax.annotation.processing.SupportedAnnotationTypes;
  130.76 +import javax.annotation.processing.SupportedSourceVersion;
  130.77 +import javax.lang.model.SourceVersion;
  130.78 +import javax.lang.model.element.AnnotationMirror;
  130.79 +import javax.lang.model.element.AnnotationValue;
  130.80 +import javax.lang.model.element.Element;
  130.81 +import javax.lang.model.element.ElementKind;
  130.82 +import javax.lang.model.element.ExecutableElement;
  130.83 +import javax.lang.model.element.Modifier;
  130.84 +import javax.lang.model.element.PackageElement;
  130.85 +import javax.lang.model.element.TypeElement;
  130.86 +import javax.lang.model.element.VariableElement;
  130.87 +import javax.lang.model.type.ArrayType;
  130.88 +import javax.lang.model.type.DeclaredType;
  130.89 +import javax.lang.model.type.MirroredTypeException;
  130.90 +import javax.lang.model.type.TypeKind;
  130.91 +import javax.lang.model.type.TypeMirror;
  130.92 +import javax.lang.model.util.Elements;
  130.93 +import javax.lang.model.util.Types;
  130.94 +import javax.tools.Diagnostic;
  130.95 +import javax.tools.FileObject;
  130.96 +import net.java.html.json.ComputedProperty;
  130.97 +import net.java.html.json.Model;
  130.98 +import net.java.html.json.Function;
  130.99 +import net.java.html.json.ModelOperation;
 130.100 +import net.java.html.json.OnPropertyChange;
 130.101 +import net.java.html.json.OnReceive;
 130.102 +import net.java.html.json.Property;
 130.103 +import org.openide.util.lookup.ServiceProvider;
 130.104 +
 130.105 +/** Annotation processor to process {@link Model @Model} annotations and
 130.106 + * generate appropriate model classes.
 130.107 + *
 130.108 + * @author Jaroslav Tulach <jtulach@netbeans.org>
 130.109 + */
 130.110 +@ServiceProvider(service=Processor.class)
 130.111 +@SupportedSourceVersion(SourceVersion.RELEASE_6)
 130.112 +@SupportedAnnotationTypes({
 130.113 +    "net.java.html.json.Model",
 130.114 +    "net.java.html.json.ModelOperation",
 130.115 +    "net.java.html.json.Function",
 130.116 +    "net.java.html.json.OnReceive",
 130.117 +    "net.java.html.json.OnPropertyChange",
 130.118 +    "net.java.html.json.ComputedProperty",
 130.119 +    "net.java.html.json.Property"
 130.120 +})
 130.121 +public final class ModelProcessor extends AbstractProcessor {
 130.122 +    private static final Logger LOG = Logger.getLogger(ModelProcessor.class.getName());
 130.123 +    private final Map<Element,String> models = new WeakHashMap<Element,String>();
 130.124 +    private final Map<Element,Prprt[]> verify = new WeakHashMap<Element,Prprt[]>();
 130.125 +    @Override
 130.126 +    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
 130.127 +        boolean ok = true;
 130.128 +        for (Element e : roundEnv.getElementsAnnotatedWith(Model.class)) {
 130.129 +            if (!processModel(e)) {
 130.130 +                ok = false;
 130.131 +            }
 130.132 +        }
 130.133 +        if (roundEnv.processingOver()) {
 130.134 +            models.clear();
 130.135 +            for (Map.Entry<Element, Prprt[]> entry : verify.entrySet()) {
 130.136 +                TypeElement te = (TypeElement)entry.getKey();
 130.137 +                String fqn = processingEnv.getElementUtils().getBinaryName(te).toString();
 130.138 +                Element finalElem = processingEnv.getElementUtils().getTypeElement(fqn);
 130.139 +                if (finalElem == null) {
 130.140 +                    continue;
 130.141 +                }
 130.142 +                Prprt[] props;
 130.143 +                Model m = finalElem.getAnnotation(Model.class);
 130.144 +                if (m == null) {
 130.145 +                    continue;
 130.146 +                }
 130.147 +                props = Prprt.wrap(processingEnv, finalElem, m.properties());
 130.148 +                for (Prprt p : props) {
 130.149 +                    boolean[] isModel = { false };
 130.150 +                    boolean[] isEnum = { false };
 130.151 +                    boolean[] isPrimitive = { false };
 130.152 +                    String t = checkType(p, isModel, isEnum, isPrimitive);
 130.153 +                    if (isEnum[0]) {
 130.154 +                        continue;
 130.155 +                    }
 130.156 +                    if (isPrimitive[0]) {
 130.157 +                        continue;
 130.158 +                    }
 130.159 +                    if (isModel[0]) {
 130.160 +                        continue;
 130.161 +                    }
 130.162 +                    if ("java.lang.String".equals(t)) {
 130.163 +                        continue;
 130.164 +                    }
 130.165 +                    error("The type " + t + " should be defined by @Model annotation", entry.getKey());
 130.166 +                }
 130.167 +            }
 130.168 +            verify.clear();
 130.169 +        }
 130.170 +        return ok;
 130.171 +    }
 130.172 +
 130.173 +    private void error(String msg, Element e) {
 130.174 +        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e);
 130.175 +    }
 130.176 +    
 130.177 +    private boolean processModel(Element e) {
 130.178 +        boolean ok = true;
 130.179 +        Model m = e.getAnnotation(Model.class);
 130.180 +        if (m == null) {
 130.181 +            return true;
 130.182 +        }
 130.183 +        String pkg = findPkgName(e);
 130.184 +        Writer w;
 130.185 +        String className = m.className();
 130.186 +        models.put(e, className);
 130.187 +        try {
 130.188 +            StringWriter body = new StringWriter();
 130.189 +            List<String> propsGetSet = new ArrayList<String>();
 130.190 +            List<String> functions = new ArrayList<String>();
 130.191 +            Map<String, Collection<String>> propsDeps = new HashMap<String, Collection<String>>();
 130.192 +            Map<String, Collection<String>> functionDeps = new HashMap<String, Collection<String>>();
 130.193 +            Prprt[] props = createProps(e, m.properties());
 130.194 +            
 130.195 +            if (!generateComputedProperties(body, props, e.getEnclosedElements(), propsGetSet, propsDeps)) {
 130.196 +                ok = false;
 130.197 +            }
 130.198 +            if (!generateOnChange(e, propsDeps, props, className, functionDeps)) {
 130.199 +                ok = false;
 130.200 +            }
 130.201 +            if (!generateProperties(e, body, props, propsGetSet, propsDeps, functionDeps)) {
 130.202 +                ok = false;
 130.203 +            }
 130.204 +            if (!generateFunctions(e, body, className, e.getEnclosedElements(), functions)) {
 130.205 +                ok = false;
 130.206 +            }
 130.207 +            if (!generateReceive(e, body, className, e.getEnclosedElements(), functions)) {
 130.208 +                ok = false;
 130.209 +            }
 130.210 +            if (!generateOperation(e, body, className, e.getEnclosedElements())) {
 130.211 +                ok = false;
 130.212 +            }
 130.213 +            FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
 130.214 +            w = new OutputStreamWriter(java.openOutputStream());
 130.215 +            try {
 130.216 +                w.append("package " + pkg + ";\n");
 130.217 +                w.append("import net.java.html.json.*;\n");
 130.218 +                w.append("public final class ").append(className).append(" implements Cloneable {\n");
 130.219 +                w.append("  private boolean locked;\n");
 130.220 +                w.append("  private net.java.html.BrwsrCtx context;\n");
 130.221 +                w.append("  private org.netbeans.html.json.impl.Bindings[] ko = { null };\n");
 130.222 +                w.append(body.toString());
 130.223 +                w.append("  private static Class<" + inPckName(e) + "> modelFor() { return null; }\n");
 130.224 +                w.append("  private ").append(className).append("(net.java.html.BrwsrCtx context) {\n");
 130.225 +                w.append("    this.context = context;\n");
 130.226 +                w.append("  };\n");
 130.227 +                w.append("  public ").append(className).append("() {\n");
 130.228 +                w.append("    this(net.java.html.BrwsrCtx.findDefault(").append(className).append(".class));\n");
 130.229 +                for (Prprt p : props) {
 130.230 +                    if (p.array()) {
 130.231 +                        continue;
 130.232 +                    }
 130.233 +                    boolean[] isModel = {false};
 130.234 +                    boolean[] isEnum = {false};
 130.235 +                    boolean isPrimitive[] = {false};
 130.236 +                    String tn = checkType(p, isModel, isEnum, isPrimitive);
 130.237 +                    if (isModel[0]) {
 130.238 +                        w.write("    prop_" + p.name() + " = new " + tn + "();\n");
 130.239 +                    }
 130.240 +                }
 130.241 +                w.append("  };\n");
 130.242 +                if (props.length > 0) {
 130.243 +                    w.append("  public ").append(className).append("(");
 130.244 +                    Prprt firstArray = null;
 130.245 +                    String sep = "";
 130.246 +                    for (Prprt p : props) {
 130.247 +                        if (p.array()) {
 130.248 +                            if (firstArray == null) {
 130.249 +                                firstArray = p;
 130.250 +                            }
 130.251 +                            continue;
 130.252 +                        }
 130.253 +                        String tn = typeName(e, p);
 130.254 +                        w.write(sep);
 130.255 +                        w.write(tn);
 130.256 +                        w.write(" " + p.name());
 130.257 +                        sep = ", ";
 130.258 +                    }
 130.259 +                    if (firstArray != null) {
 130.260 +                        String tn;
 130.261 +                        boolean[] isModel = {false};
 130.262 +                        boolean[] isEnum = {false};
 130.263 +                        boolean isPrimitive[] = {false};
 130.264 +                        tn = checkType(firstArray, isModel, isEnum, isPrimitive);
 130.265 +                        w.write(sep);
 130.266 +                        w.write(tn);
 130.267 +                        w.write("... " + firstArray.name());
 130.268 +                    }
 130.269 +                    w.append(") {\n");
 130.270 +                    w.append("    this(net.java.html.BrwsrCtx.findDefault(").append(className).append(".class));\n");
 130.271 +                    for (Prprt p : props) {
 130.272 +                        if (p.array()) {
 130.273 +                            continue;
 130.274 +                        }
 130.275 +                        w.write("    this.prop_" + p.name() + " = " + p.name() + ";\n");
 130.276 +                    }
 130.277 +                    if (firstArray != null) {
 130.278 +                        w.write("    this.prop_" + firstArray.name() + ".init(" + firstArray.name() + ");\n");
 130.279 +                    }
 130.280 +                    w.append("  };\n");
 130.281 +                }
 130.282 +                w.append("  private org.netbeans.html.json.impl.Bindings intKnckt() {\n");
 130.283 +                w.append("    if (ko[0] != null) return ko[0];\n");
 130.284 +                w.append("    ko[0] = org.netbeans.html.json.impl.Bindings.apply(context, this);\n");
 130.285 +                {
 130.286 +                    w.append("    org.apidesign.html.json.spi.PropertyBinding[] propArr = {\n");
 130.287 +                    for (int i = 0; i < propsGetSet.size(); i += 5) {
 130.288 +                        w.append("      ko[0].registerProperty(\"").append(propsGetSet.get(i)).append("\", this, new P(");
 130.289 +                        w.append((i / 5) + "), " + (propsGetSet.get(i + 2) == null) + "),\n");
 130.290 +                    }
 130.291 +                    w.append("    };\n");
 130.292 +                }
 130.293 +                {
 130.294 +                    w.append("    org.apidesign.html.json.spi.FunctionBinding[] funcArr = {\n");
 130.295 +                    for (int i = 0; i < functions.size(); i += 2) {
 130.296 +                        w.append("      ko[0].registerFunction(\"").append(functions.get(i)).append("\", this, new P(");
 130.297 +                        w.append((i / 2) + ")),\n");
 130.298 +                    }
 130.299 +                    w.append("    };\n");
 130.300 +                }
 130.301 +                w.append("    ko[0].finish(this, propArr, funcArr);\n");
 130.302 +                w.append("    return ko[0];\n");
 130.303 +                w.append("  };\n");
 130.304 +                w.append("  private static final class P implements org.netbeans.html.json.impl.SetAndGet<" + className + ">,\n");
 130.305 +                w.append("  org.netbeans.html.json.impl.Callback<" + className + ">,\n");
 130.306 +                w.append("  org.netbeans.html.json.impl.FromJSON<" + className + "> {\n");
 130.307 +                w.append("    private final int type;\n");
 130.308 +                w.append("    P(int t) { type = t; };\n");
 130.309 +                w.append("    public void setValue(" + className + " data, Object value) {\n");
 130.310 +                w.append("      switch (type) {\n");
 130.311 +                for (int i = 0; i < propsGetSet.size(); i += 5) {
 130.312 +                    final String set = propsGetSet.get(i + 2);
 130.313 +                    String tn = propsGetSet.get(i + 4);
 130.314 +                    String btn = findBoxedType(tn);
 130.315 +                    if (btn != null) {
 130.316 +                        tn = btn;
 130.317 +                    }
 130.318 +                    if (set != null) {
 130.319 +                        w.append("        case " + (i / 5) + ": data." + strip(set) + "(org.netbeans.html.json.impl.JSON.extractValue(" + tn + ".class, value)); return;\n");
 130.320 +                    }
 130.321 +                }
 130.322 +                w.append("      }\n");
 130.323 +                w.append("    }\n");
 130.324 +                w.append("    public Object getValue(" + className + " data) {\n");
 130.325 +                w.append("      switch (type) {\n");
 130.326 +                for (int i = 0; i < propsGetSet.size(); i += 5) {
 130.327 +                    final String get = propsGetSet.get(i + 1);
 130.328 +                    if (get != null) {
 130.329 +                        w.append("        case " + (i / 5) + ": return data." + strip(get) + "();\n");
 130.330 +                    }
 130.331 +                }
 130.332 +                w.append("      }\n");
 130.333 +                w.append("      throw new UnsupportedOperationException();\n");
 130.334 +                w.append("    }\n");
 130.335 +                w.append("    public void call(" + className + " model, Object data, Object ev) {\n");
 130.336 +                w.append("      switch (type) {\n");
 130.337 +                for (int i = 0; i < functions.size(); i += 2) {
 130.338 +                    final String name = functions.get(i);
 130.339 +                    w.append("        case " + (i / 2) + ": model." + name + "(data, ev); return;\n");
 130.340 +                }
 130.341 +                w.append("      }\n");
 130.342 +                w.append("      throw new UnsupportedOperationException();\n");
 130.343 +                w.append("    }\n");
 130.344 +                w.append("    public Class<" + className + "> factoryFor() { return " + className + ".class; }\n");
 130.345 +                w.append("    public " + className + " read(net.java.html.BrwsrCtx c, Object json) { return new " + className + "(c, json); }\n");
 130.346 +                w.append("    public " + className + " cloneTo(Object o, net.java.html.BrwsrCtx c) { return ((" + className + ")o).clone(c); }\n");
 130.347 +                w.append("  }\n");
 130.348 +                w.append("  static { org.netbeans.html.json.impl.JSON.register(new P(0)); }\n");
 130.349 +                w.append("  private ").append(className).append("(net.java.html.BrwsrCtx c, Object json) {\n");
 130.350 +                w.append("    this.context = c;\n");
 130.351 +                int values = 0;
 130.352 +                for (int i = 0; i < propsGetSet.size(); i += 5) {
 130.353 +                    Prprt p = findPrprt(props, propsGetSet.get(i));
 130.354 +                    if (p == null) {
 130.355 +                        continue;
 130.356 +                    }
 130.357 +                    values++;
 130.358 +                }
 130.359 +                w.append("    Object[] ret = new Object[" + values + "];\n");
 130.360 +                w.append("    org.netbeans.html.json.impl.JSON.extract(context, json, new String[] {\n");
 130.361 +                for (int i = 0; i < propsGetSet.size(); i += 5) {
 130.362 +                    Prprt p = findPrprt(props, propsGetSet.get(i));
 130.363 +                    if (p == null) {
 130.364 +                        continue;
 130.365 +                    }
 130.366 +                    w.append("      \"").append(propsGetSet.get(i)).append("\",\n");
 130.367 +                }
 130.368 +                w.append("    }, ret);\n");
 130.369 +                for (int i = 0, cnt = 0, prop = 0; i < propsGetSet.size(); i += 5) {
 130.370 +                    final String pn = propsGetSet.get(i);
 130.371 +                    Prprt p = findPrprt(props, pn);
 130.372 +                    if (p == null) {
 130.373 +                        continue;
 130.374 +                    }
 130.375 +                    boolean[] isModel = { false };
 130.376 +                    boolean[] isEnum = { false };
 130.377 +                    boolean isPrimitive[] = { false };
 130.378 +                    String type = checkType(props[prop++], isModel, isEnum, isPrimitive);
 130.379 +                    if (p.array()) {
 130.380 +                        w.append("    if (ret[" + cnt + "] instanceof Object[]) {\n");
 130.381 +                        w.append("      for (Object e : ((Object[])ret[" + cnt + "])) {\n");
 130.382 +                        if (isModel[0]) {
 130.383 +                            w.append("        this.prop_").append(pn).append(".add(org.netbeans.html.json.impl.JSON.read");
 130.384 +                            w.append("(c, " + type + ".class, e));\n");
 130.385 +                        } else if (isEnum[0]) {
 130.386 +                            w.append("        this.prop_").append(pn);
 130.387 +                            w.append(".add(e == null ? null : ");
 130.388 +                            w.append(type).append(".valueOf(org.netbeans.html.json.impl.JSON.stringValue(e)));\n");
 130.389 +                        } else {
 130.390 +                            if (isPrimitive(type)) {
 130.391 +                                w.append("        this.prop_").append(pn).append(".add(org.netbeans.html.json.impl.JSON.numberValue(e).");
 130.392 +                                w.append(type).append("Value());\n");
 130.393 +                            } else {
 130.394 +                                w.append("        this.prop_").append(pn).append(".add((");
 130.395 +                                w.append(type).append(")e);\n");
 130.396 +                            }
 130.397 +                        }
 130.398 +                        w.append("      }\n");
 130.399 +                        w.append("    }\n");
 130.400 +                    } else {
 130.401 +                        if (isEnum[0]) {
 130.402 +                            w.append("    try {\n");
 130.403 +                            w.append("    this.prop_").append(pn);
 130.404 +                            w.append(" = ret[" + cnt + "] == null ? null : ");
 130.405 +                            w.append(type).append(".valueOf(org.netbeans.html.json.impl.JSON.stringValue(ret[" + cnt + "]));\n");
 130.406 +                            w.append("    } catch (IllegalArgumentException ex) {\n");
 130.407 +                            w.append("      ex.printStackTrace();\n");
 130.408 +                            w.append("    }\n");
 130.409 +                        } else if (isPrimitive(type)) {
 130.410 +                            w.append("    this.prop_").append(pn);
 130.411 +                            w.append(" = ret[" + cnt + "] == null ? ");
 130.412 +                            if ("char".equals(type)) {
 130.413 +                                w.append("0 : (org.netbeans.html.json.impl.JSON.charValue(");
 130.414 +                            } else if ("boolean".equals(type)) {
 130.415 +                                w.append("false : (org.netbeans.html.json.impl.JSON.boolValue(");
 130.416 +                            } else {
 130.417 +                                w.append("0 : (org.netbeans.html.json.impl.JSON.numberValue(");
 130.418 +                            }
 130.419 +                            w.append("ret[" + cnt + "])).");
 130.420 +                            w.append(type).append("Value();\n");
 130.421 +                        } else if (isModel[0]) {
 130.422 +                            w.append("    this.prop_").append(pn).append(" = org.netbeans.html.json.impl.JSON.read");
 130.423 +                            w.append("(c, " + type + ".class, ");
 130.424 +                            w.append("ret[" + cnt + "]);\n");
 130.425 +                        }else {
 130.426 +                            w.append("    this.prop_").append(pn);
 130.427 +                            w.append(" = (").append(type).append(')');
 130.428 +                            w.append("ret[" + cnt + "];\n");
 130.429 +                        }
 130.430 +                    }
 130.431 +                    cnt++;
 130.432 +                }
 130.433 +                w.append("  };\n");
 130.434 +                writeToString(props, w);
 130.435 +                writeClone(className, props, w);
 130.436 +                w.write("  /** Activates this model instance in the current {@link \n"
 130.437 +                    + "net.java.html.json.Models#bind(java.lang.Object, net.java.html.BrwsrCtx) browser context}. \n"
 130.438 +                    + "In case of using Knockout technology, this means to \n"
 130.439 +                    + "bind JSON like data in this model instance with Knockout tags in \n"
 130.440 +                    + "the surrounding HTML page.\n"
 130.441 +                    + "*/\n"
 130.442 +                );
 130.443 +                w.write("  public " + className + " applyBindings() {\n");
 130.444 +                w.write("    intKnckt().applyBindings();\n");
 130.445 +                w.write("    return this;\n");
 130.446 +                w.write("  }\n");
 130.447 +                w.write("  public boolean equals(Object o) {\n");
 130.448 +                w.write("    if (o == this) return true;\n");
 130.449 +                w.write("    if (o instanceof org.netbeans.html.json.impl.WrapperObject) {\n");
 130.450 +                w.write("      ((org.netbeans.html.json.impl.WrapperObject)o).setRealObject(intKnckt().koData());\n");
 130.451 +                w.write("      return false;\n");
 130.452 +                w.write("    }\n");
 130.453 +                w.write("    if (!(o instanceof " + className + ")) return false;\n");
 130.454 +                w.write("    " + className + " p = (" + className + ")o;\n");
 130.455 +                for (Prprt p : props) {
 130.456 +                    w.write("    if (!org.netbeans.html.json.impl.JSON.isSame(prop_" + p.name() + ", p.prop_" + p.name() + ")) return false;\n");
 130.457 +                }
 130.458 +                w.write("    return true;\n");
 130.459 +                w.write("  }\n");
 130.460 +                w.write("  public int hashCode() {\n");
 130.461 +                w.write("    int h = " + className + ".class.getName().hashCode();\n");
 130.462 +                for (Prprt p : props) {
 130.463 +                    w.write("    h = org.netbeans.html.json.impl.JSON.hashPlus(prop_" + p.name() + ", h);\n");
 130.464 +                }
 130.465 +                w.write("    return h;\n");
 130.466 +                w.write("  }\n");
 130.467 +                w.write("}\n");
 130.468 +            } finally {
 130.469 +                w.close();
 130.470 +            }
 130.471 +        } catch (IOException ex) {
 130.472 +            error("Can't create " + className + ".java", e);
 130.473 +            return false;
 130.474 +        }
 130.475 +        return ok;
 130.476 +    }
 130.477 +    
 130.478 +    private boolean generateProperties(
 130.479 +        Element where,
 130.480 +        Writer w, Prprt[] properties,
 130.481 +        Collection<String> props, 
 130.482 +        Map<String,Collection<String>> deps,
 130.483 +        Map<String,Collection<String>> functionDeps
 130.484 +    ) throws IOException {
 130.485 +        boolean ok = true;
 130.486 +        for (Prprt p : properties) {
 130.487 +            final String tn;
 130.488 +            tn = typeName(where, p);
 130.489 +            String[] gs = toGetSet(p.name(), tn, p.array());
 130.490 +            String castTo;
 130.491 +            
 130.492 +            if (p.array()) {
 130.493 +                w.write("  private org.netbeans.html.json.impl.JSONList<" + tn + "> prop_" + p.name() + " = new org.netbeans.html.json.impl.JSONList<" + tn + ">(ko, \""
 130.494 +                    + p.name() + "\"");
 130.495 +                Collection<String> dependants = deps.get(p.name());
 130.496 +                if (dependants != null) {
 130.497 +                    for (String depProp : dependants) {
 130.498 +                        w.write(", ");
 130.499 +                        w.write('\"');
 130.500 +                        w.write(depProp);
 130.501 +                        w.write('\"');
 130.502 +                    }
 130.503 +                }
 130.504 +                w.write(")");
 130.505 +                
 130.506 +                dependants = functionDeps.get(p.name());
 130.507 +                if (dependants != null) {
 130.508 +                    w.write(".onChange(new Runnable() { public void run() {\n");
 130.509 +                    for (String call : dependants) {
 130.510 +                        w.append("  ").append(call);
 130.511 +                    }
 130.512 +                    w.write("  }})");
 130.513 +                }
 130.514 +                w.write(";\n");
 130.515 +            
 130.516 +                castTo = "java.util.List";
 130.517 +                w.write("  public java.util.List<" + tn + "> " + gs[0] + "() {\n");
 130.518 +                w.write("    if (locked) throw new IllegalStateException();\n");
 130.519 +                w.write("    return prop_" + p.name() + ";\n");
 130.520 +                w.write("  }\n");
 130.521 +            } else {
 130.522 +                castTo = tn;
 130.523 +                w.write("  private " + tn + " prop_" + p.name() + ";\n");
 130.524 +                w.write("  public " + tn + " " + gs[0] + "() {\n");
 130.525 +                w.write("    if (locked) throw new IllegalStateException();\n");
 130.526 +                w.write("    return prop_" + p.name() + ";\n");
 130.527 +                w.write("  }\n");
 130.528 +                w.write("  public void " + gs[1] + "(" + tn + " v) {\n");
 130.529 +                w.write("    if (locked) throw new IllegalStateException();\n");
 130.530 +                w.write("    if (org.netbeans.html.json.impl.JSON.isSame(prop_" + p.name() + ", v)) return;\n");
 130.531 +                w.write("    prop_" + p.name() + " = v;\n");
 130.532 +                w.write("    org.netbeans.html.json.impl.Bindings b = ko[0];\n");
 130.533 +                w.write("    if (b != null) {\n");
 130.534 +                w.write("      b.valueHasMutated(\"" + p.name() + "\");\n");
 130.535 +                Collection<String> dependants = deps.get(p.name());
 130.536 +                if (dependants != null) {
 130.537 +                    for (String depProp : dependants) {
 130.538 +                        w.write("      b.valueHasMutated(\"" + depProp + "\");\n");
 130.539 +                    }
 130.540 +                }
 130.541 +                w.write("    }\n");
 130.542 +                dependants = functionDeps.get(p.name());
 130.543 +                if (dependants != null) {
 130.544 +                    for (String call : dependants) {
 130.545 +                        w.append("  ").append(call);
 130.546 +                    }
 130.547 +                }
 130.548 +                w.write("  }\n");
 130.549 +            }
 130.550 +            
 130.551 +            props.add(p.name());
 130.552 +            props.add(gs[2]);
 130.553 +            props.add(gs[3]);
 130.554 +            props.add(gs[0]);
 130.555 +            props.add(castTo);
 130.556 +        }
 130.557 +        return ok;
 130.558 +    }
 130.559 +
 130.560 +    private boolean generateComputedProperties(
 130.561 +        Writer w, Prprt[] fixedProps,
 130.562 +        Collection<? extends Element> arr, Collection<String> props,
 130.563 +        Map<String,Collection<String>> deps
 130.564 +    ) throws IOException {
 130.565 +        boolean ok = true;
 130.566 +        for (Element e : arr) {
 130.567 +            if (e.getKind() != ElementKind.METHOD) {
 130.568 +                continue;
 130.569 +            }
 130.570 +            if (e.getAnnotation(ComputedProperty.class) == null) {
 130.571 +                continue;
 130.572 +            }
 130.573 +            if (!e.getModifiers().contains(Modifier.STATIC)) {
 130.574 +                error("Method " + e.getSimpleName() + " has to be static when annotated by @ComputedProperty", e);
 130.575 +                ok = false;
 130.576 +                continue;
 130.577 +            }
 130.578 +            ExecutableElement ee = (ExecutableElement)e;
 130.579 +            final TypeMirror rt = ee.getReturnType();
 130.580 +            final Types tu = processingEnv.getTypeUtils();
 130.581 +            TypeMirror ert = tu.erasure(rt);
 130.582 +            String tn = fqn(ert, ee);
 130.583 +            boolean array = false;
 130.584 +            final TypeMirror toCheck;
 130.585 +            if (tn.equals("java.util.List")) {
 130.586 +                array = true;
 130.587 +                toCheck = ((DeclaredType)rt).getTypeArguments().get(0);
 130.588 +            } else {
 130.589 +                toCheck = rt;
 130.590 +            }
 130.591 +            
 130.592 +            final String sn = ee.getSimpleName().toString();
 130.593 +            
 130.594 +            if (toCheck.getKind().isPrimitive()) {
 130.595 +                // OK
 130.596 +            } else {
 130.597 +                TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
 130.598 +                TypeMirror enumType = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType();
 130.599 +
 130.600 +                if (tu.isSubtype(toCheck, stringType)) {
 130.601 +                    // OK
 130.602 +                } else if (tu.isSubtype(tu.erasure(toCheck), tu.erasure(enumType))) {
 130.603 +                    // OK
 130.604 +                } else if (isModel(toCheck)) {
 130.605 +                    // OK
 130.606 +                } else {
 130.607 +                    ok = false;
 130.608 +                    error(sn + " cannot return " + toCheck, e);
 130.609 +                }
 130.610 +            }
 130.611 +            
 130.612 +            String[] gs = toGetSet(sn, tn, array);
 130.613 +            
 130.614 +            w.write("  public " + tn + " " + gs[0] + "() {\n");
 130.615 +            w.write("    if (locked) throw new IllegalStateException();\n");
 130.616 +            int arg = 0;
 130.617 +            for (VariableElement pe : ee.getParameters()) {
 130.618 +                final String dn = pe.getSimpleName().toString();
 130.619 +                
 130.620 +                if (!verifyPropName(pe, dn, fixedProps)) {
 130.621 +                    ok = false;
 130.622 +                }
 130.623 +                
 130.624 +                final String dt = fqn(pe.asType(), ee);
 130.625 +                String[] call = toGetSet(dn, dt, false);
 130.626 +                w.write("    " + dt + " arg" + (++arg) + " = ");
 130.627 +                w.write(call[0] + "();\n");
 130.628 +                
 130.629 +                Collection<String> depends = deps.get(dn);
 130.630 +                if (depends == null) {
 130.631 +                    depends = new LinkedHashSet<String>();
 130.632 +                    deps.put(dn, depends);
 130.633 +                }
 130.634 +                depends.add(sn);
 130.635 +            }
 130.636 +            w.write("    try {\n");
 130.637 +            w.write("      locked = true;\n");
 130.638 +            w.write("      return " + fqn(ee.getEnclosingElement().asType(), ee) + '.' + e.getSimpleName() + "(");
 130.639 +            String sep = "";
 130.640 +            for (int i = 1; i <= arg; i++) {
 130.641 +                w.write(sep);
 130.642 +                w.write("arg" + i);
 130.643 +                sep = ", ";
 130.644 +            }
 130.645 +            w.write(");\n");
 130.646 +            w.write("    } finally {\n");
 130.647 +            w.write("      locked = false;\n");
 130.648 +            w.write("    }\n");
 130.649 +            w.write("  }\n");
 130.650 +
 130.651 +            props.add(e.getSimpleName().toString());
 130.652 +            props.add(gs[2]);
 130.653 +            props.add(null);
 130.654 +            props.add(gs[0]);
 130.655 +            props.add(tn);
 130.656 +        }
 130.657 +        
 130.658 +        return ok;
 130.659 +    }
 130.660 +
 130.661 +    private static String[] toGetSet(String name, String type, boolean array) {
 130.662 +        String n = Character.toUpperCase(name.charAt(0)) + name.substring(1);
 130.663 +        String bck2brwsrType = "L" + type.replace('.', '_') + "_2";
 130.664 +        if ("int".equals(type)) {
 130.665 +            bck2brwsrType = "I";
 130.666 +        }
 130.667 +        if ("double".equals(type)) {
 130.668 +            bck2brwsrType = "D";
 130.669 +        }
 130.670 +        String pref = "get";
 130.671 +        if ("boolean".equals(type)) {
 130.672 +            pref = "is";
 130.673 +            bck2brwsrType = "Z";
 130.674 +        }
 130.675 +        final String nu = n.replace('.', '_');
 130.676 +        if (array) {
 130.677 +            return new String[] { 
 130.678 +                "get" + n,
 130.679 +                null,
 130.680 +                "get" + nu + "__Ljava_util_List_2",
 130.681 +                null
 130.682 +            };
 130.683 +        }
 130.684 +        return new String[]{
 130.685 +            pref + n, 
 130.686 +            "set" + n, 
 130.687 +            pref + nu + "__" + bck2brwsrType,
 130.688 +            "set" + nu + "__V" + bck2brwsrType
 130.689 +        };
 130.690 +    }
 130.691 +
 130.692 +    private String typeName(Element where, Prprt p) {
 130.693 +        String ret;
 130.694 +        boolean[] isModel = { false };
 130.695 +        boolean[] isEnum = { false };
 130.696 +        boolean isPrimitive[] = { false };
 130.697 +        ret = checkType(p, isModel, isEnum, isPrimitive);
 130.698 +        if (p.array()) {
 130.699 +            String bt = findBoxedType(ret);
 130.700 +            if (bt != null) {
 130.701 +                return bt;
 130.702 +            }
 130.703 +        }
 130.704 +        return ret;
 130.705 +    }
 130.706 +    
 130.707 +    private static String findBoxedType(String ret) {
 130.708 +        if (ret.equals("boolean")) {
 130.709 +            return Boolean.class.getName();
 130.710 +        }
 130.711 +        if (ret.equals("byte")) {
 130.712 +            return Byte.class.getName();
 130.713 +        }
 130.714 +        if (ret.equals("short")) {
 130.715 +            return Short.class.getName();
 130.716 +        }
 130.717 +        if (ret.equals("char")) {
 130.718 +            return Character.class.getName();
 130.719 +        }
 130.720 +        if (ret.equals("int")) {
 130.721 +            return Integer.class.getName();
 130.722 +        }
 130.723 +        if (ret.equals("long")) {
 130.724 +            return Long.class.getName();
 130.725 +        }
 130.726 +        if (ret.equals("float")) {
 130.727 +            return Float.class.getName();
 130.728 +        }
 130.729 +        if (ret.equals("double")) {
 130.730 +            return Double.class.getName();
 130.731 +        }
 130.732 +        return null;
 130.733 +    }
 130.734 +
 130.735 +    private boolean verifyPropName(Element e, String propName, Prprt[] existingProps) {
 130.736 +        StringBuilder sb = new StringBuilder();
 130.737 +        String sep = "";
 130.738 +        for (Prprt Prprt : existingProps) {
 130.739 +            if (Prprt.name().equals(propName)) {
 130.740 +                return true;
 130.741 +            }
 130.742 +            sb.append(sep);
 130.743 +            sb.append('"');
 130.744 +            sb.append(Prprt.name());
 130.745 +            sb.append('"');
 130.746 +            sep = ", ";
 130.747 +        }
 130.748 +        error(
 130.749 +            propName + " is not one of known properties: " + sb
 130.750 +            , e
 130.751 +        );
 130.752 +        return false;
 130.753 +    }
 130.754 +
 130.755 +    private static String findPkgName(Element e) {
 130.756 +        for (;;) {
 130.757 +            if (e.getKind() == ElementKind.PACKAGE) {
 130.758 +                return ((PackageElement)e).getQualifiedName().toString();
 130.759 +            }
 130.760 +            e = e.getEnclosingElement();
 130.761 +        }
 130.762 +    }
 130.763 +
 130.764 +    private boolean generateFunctions(
 130.765 +        Element clazz, StringWriter body, String className, 
 130.766 +        List<? extends Element> enclosedElements, List<String> functions
 130.767 +    ) {
 130.768 +        for (Element m : enclosedElements) {
 130.769 +            if (m.getKind() != ElementKind.METHOD) {
 130.770 +                continue;
 130.771 +            }
 130.772 +            ExecutableElement e = (ExecutableElement)m;
 130.773 +            Function onF = e.getAnnotation(Function.class);
 130.774 +            if (onF == null) {
 130.775 +                continue;
 130.776 +            }
 130.777 +            if (!e.getModifiers().contains(Modifier.STATIC)) {
 130.778 +                error("@OnFunction method needs to be static", e);
 130.779 +                return false;
 130.780 +            }
 130.781 +            if (e.getModifiers().contains(Modifier.PRIVATE)) {
 130.782 +                error("@OnFunction method cannot be private", e);
 130.783 +                return false;
 130.784 +            }
 130.785 +            if (e.getReturnType().getKind() != TypeKind.VOID) {
 130.786 +                error("@OnFunction method should return void", e);
 130.787 +                return false;
 130.788 +            }
 130.789 +            String n = e.getSimpleName().toString();
 130.790 +            body.append("  private void ").append(n).append("(Object data, Object ev) {\n");
 130.791 +            body.append("    ").append(((TypeElement)clazz).getQualifiedName()).append(".").append(n).append("(");
 130.792 +            body.append(wrapParams(e, null, className, "ev", "data"));
 130.793 +            body.append(");\n");
 130.794 +            body.append("  }\n");
 130.795 +            
 130.796 +            functions.add(n);
 130.797 +            functions.add(n + "__VLjava_lang_Object_2Ljava_lang_Object_2");
 130.798 +        }
 130.799 +        return true;
 130.800 +    }
 130.801 +
 130.802 +    private boolean generateOnChange(Element clazz, Map<String,Collection<String>> propDeps,
 130.803 +        Prprt[] properties, String className, 
 130.804 +        Map<String, Collection<String>> functionDeps
 130.805 +    ) {
 130.806 +        for (Element m : clazz.getEnclosedElements()) {
 130.807 +            if (m.getKind() != ElementKind.METHOD) {
 130.808 +                continue;
 130.809 +            }
 130.810 +            ExecutableElement e = (ExecutableElement) m;
 130.811 +            OnPropertyChange onPC = e.getAnnotation(OnPropertyChange.class);
 130.812 +            if (onPC == null) {
 130.813 +                continue;
 130.814 +            }
 130.815 +            for (String pn : onPC.value()) {
 130.816 +                if (findPrprt(properties, pn) == null && findDerivedFrom(propDeps, pn).isEmpty()) {
 130.817 +                    error("No Prprt named '" + pn + "' in the model", clazz);
 130.818 +                    return false;
 130.819 +                }
 130.820 +            }
 130.821 +            if (!e.getModifiers().contains(Modifier.STATIC)) {
 130.822 +                error("@OnPrprtChange method needs to be static", e);
 130.823 +                return false;
 130.824 +            }
 130.825 +            if (e.getModifiers().contains(Modifier.PRIVATE)) {
 130.826 +                error("@OnPrprtChange method cannot be private", e);
 130.827 +                return false;
 130.828 +            }
 130.829 +            if (e.getReturnType().getKind() != TypeKind.VOID) {
 130.830 +                error("@OnPrprtChange method should return void", e);
 130.831 +                return false;
 130.832 +            }
 130.833 +            String n = e.getSimpleName().toString();
 130.834 +            
 130.835 +            
 130.836 +            for (String pn : onPC.value()) {
 130.837 +                StringBuilder call = new StringBuilder();
 130.838 +                call.append("  ").append(clazz.getSimpleName()).append(".").append(n).append("(");
 130.839 +                call.append(wrapPropName(e, className, "name", pn));
 130.840 +                call.append(");\n");
 130.841 +                
 130.842 +                Collection<String> change = functionDeps.get(pn);
 130.843 +                if (change == null) {
 130.844 +                    change = new ArrayList<String>();
 130.845 +                    functionDeps.put(pn, change);
 130.846 +                }
 130.847 +                change.add(call.toString());
 130.848 +                for (String dpn : findDerivedFrom(propDeps, pn)) {
 130.849 +                    change = functionDeps.get(dpn);
 130.850 +                    if (change == null) {
 130.851 +                        change = new ArrayList<String>();
 130.852 +                        functionDeps.put(dpn, change);
 130.853 +                    }
 130.854 +                    change.add(call.toString());
 130.855 +                }
 130.856 +            }
 130.857 +        }
 130.858 +        return true;
 130.859 +    }
 130.860 +
 130.861 +    private boolean generateOperation(Element clazz, 
 130.862 +        StringWriter body, String className, 
 130.863 +        List<? extends Element> enclosedElements
 130.864 +    ) {
 130.865 +        for (Element m : enclosedElements) {
 130.866 +            if (m.getKind() != ElementKind.METHOD) {
 130.867 +                continue;
 130.868 +            }
 130.869 +            ExecutableElement e = (ExecutableElement)m;
 130.870 +            ModelOperation mO = e.getAnnotation(ModelOperation.class);
 130.871 +            if (mO == null) {
 130.872 +                continue;
 130.873 +            }
 130.874 +            if (!e.getModifiers().contains(Modifier.STATIC)) {
 130.875 +                error("@ModelOperation method needs to be static", e);
 130.876 +                return false;
 130.877 +            }
 130.878 +            if (e.getModifiers().contains(Modifier.PRIVATE)) {
 130.879 +                error("@ModelOperation method cannot be private", e);
 130.880 +                return false;
 130.881 +            }
 130.882 +            if (e.getReturnType().getKind() != TypeKind.VOID) {
 130.883 +                error("@ModelOperation method should return void", e);
 130.884 +                return false;
 130.885 +            }
 130.886 +            List<String> args = new ArrayList<String>();
 130.887 +            {
 130.888 +                body.append("  public void ").append(m.getSimpleName()).append("(");
 130.889 +                String sep = "";
 130.890 +                boolean checkFirst = true;
 130.891 +                for (VariableElement ve : e.getParameters()) {
 130.892 +                    final TypeMirror type = ve.asType();
 130.893 +                    CharSequence simpleName;
 130.894 +                    if (type.getKind() == TypeKind.DECLARED) {
 130.895 +                        simpleName = ((DeclaredType)type).asElement().getSimpleName();
 130.896 +                    } else {
 130.897 +                        simpleName = type.toString();
 130.898 +                    }
 130.899 +                    if (simpleName.toString().equals(className)) {
 130.900 +                        checkFirst = false;
 130.901 +                    } else {
 130.902 +                        if (checkFirst) {
 130.903 +                            error("First parameter of @ModelOperation method must be " + className, m);
 130.904 +                            return false;
 130.905 +                        }
 130.906 +                        args.add(ve.getSimpleName().toString());
 130.907 +                        body.append(sep).append("final ");
 130.908 +                        body.append(ve.asType().toString()).append(" ");
 130.909 +                        body.append(ve.toString());
 130.910 +                        sep = ", ";
 130.911 +                    }
 130.912 +                }
 130.913 +                body.append(") {\n");
 130.914 +                body.append("    org.netbeans.html.json.impl.JSON.runInBrowser(this.context, new Runnable() { public void run() {\n");
 130.915 +                body.append("      ").append(clazz.getSimpleName()).append(".").append(m.getSimpleName()).append("(");
 130.916 +                body.append(className).append(".this");
 130.917 +                for (String s : args) {
 130.918 +                    body.append(", ").append(s);
 130.919 +                }
 130.920 +                body.append(");\n");
 130.921 +                body.append("    }});\n");
 130.922 +                body.append("  }\n");
 130.923 +            }
 130.924 +            
 130.925 +        }
 130.926 +        return true;
 130.927 +    }
 130.928 +    
 130.929 +    
 130.930 +    private boolean generateReceive(
 130.931 +        Element clazz, StringWriter body, String className, 
 130.932 +        List<? extends Element> enclosedElements, List<String> functions
 130.933 +    ) {
 130.934 +        for (Element m : enclosedElements) {
 130.935 +            if (m.getKind() != ElementKind.METHOD) {
 130.936 +                continue;
 130.937 +            }
 130.938 +            ExecutableElement e = (ExecutableElement)m;
 130.939 +            OnReceive onR = e.getAnnotation(OnReceive.class);
 130.940 +            if (onR == null) {
 130.941 +                continue;
 130.942 +            }
 130.943 +            if (!e.getModifiers().contains(Modifier.STATIC)) {
 130.944 +                error("@OnReceive method needs to be static", e);
 130.945 +                return false;
 130.946 +            }
 130.947 +            if (e.getModifiers().contains(Modifier.PRIVATE)) {
 130.948 +                error("@OnReceive method cannot be private", e);
 130.949 +                return false;
 130.950 +            }
 130.951 +            if (e.getReturnType().getKind() != TypeKind.VOID) {
 130.952 +                error("@OnReceive method should return void", e);
 130.953 +                return false;
 130.954 +            }
 130.955 +            if (!onR.jsonp().isEmpty() && !"GET".equals(onR.method())) {
 130.956 +                error("JSONP works only with GET transport method", e);
 130.957 +            }
 130.958 +            String dataMirror = findDataSpecified(e, onR);
 130.959 +            if ("PUT".equals(onR.method()) && dataMirror == null) {
 130.960 +                error("PUT method needs to specify a data() class", e);
 130.961 +                return false;
 130.962 +            }
 130.963 +            if ("POST".equals(onR.method()) && dataMirror == null) {
 130.964 +                error("POST method needs to specify a data() class", e);
 130.965 +                return false;
 130.966 +            }
 130.967 +            String modelClass = null;
 130.968 +            boolean expectsList = false;
 130.969 +            List<String> args = new ArrayList<String>();
 130.970 +            {
 130.971 +                for (VariableElement ve : e.getParameters()) {
 130.972 +                    TypeMirror modelType = null;
 130.973 +                    final TypeMirror type = ve.asType();
 130.974 +                    CharSequence simpleName;
 130.975 +                    if (type.getKind() == TypeKind.DECLARED) {
 130.976 +                        simpleName = ((DeclaredType)type).asElement().getSimpleName();
 130.977 +                    } else {
 130.978 +                        simpleName = type.toString();
 130.979 +                    }
 130.980 +                    if (simpleName.toString().equals(className)) {
 130.981 +                        args.add(className + ".this");
 130.982 +                    } else if (isModel(ve.asType())) {
 130.983 +                        modelType = ve.asType();
 130.984 +                    } else if (ve.asType().getKind() == TypeKind.ARRAY) {
 130.985 +                        modelType = ((ArrayType)ve.asType()).getComponentType();
 130.986 +                        expectsList = true;
 130.987 +                    } else if (ve.asType().toString().equals("java.lang.String")) {
 130.988 +                        modelType = ve.asType();
 130.989 +                    }
 130.990 +                    if (modelType != null) {
 130.991 +                        if (modelClass != null) {
 130.992 +                            error("There can be only one model class among arguments", e);
 130.993 +                        } else {
 130.994 +                            modelClass = modelType.toString();
 130.995 +                            if (expectsList) {
 130.996 +                                args.add("arr");
 130.997 +                            } else {
 130.998 +                                args.add("arr[0]");
 130.999 +                            }
130.1000 +                        }
130.1001 +                    }
130.1002 +                }
130.1003 +            }
130.1004 +            if (modelClass == null) {
130.1005 +                error("The method needs to have one @Model class as parameter", e);
130.1006 +            }
130.1007 +            String n = e.getSimpleName().toString();
130.1008 +            if ("WebSocket".equals(onR.method())) {
130.1009 +                body.append("  /** Performs WebSocket communication. Call with <code>null</code> data parameter\n");
130.1010 +                body.append("  * to open the connection (even if not required). Call with non-null data to\n");
130.1011 +                body.append("  * send messages to server. Call again with <code>null</code> data to close the socket.\n");
130.1012 +                body.append("  */\n");
130.1013 +            }
130.1014 +            body.append("  public void ").append(n).append("(");
130.1015 +            StringBuilder urlBefore = new StringBuilder();
130.1016 +            StringBuilder urlAfter = new StringBuilder();
130.1017 +            String jsonpVarName = null;
130.1018 +            {
130.1019 +                String sep = "";
130.1020 +                boolean skipJSONP = onR.jsonp().isEmpty();
130.1021 +                for (String p : findParamNames(e, onR.url(), onR.jsonp(), urlBefore, urlAfter)) {
130.1022 +                    if (!skipJSONP && p.equals(onR.jsonp())) {
130.1023 +                        skipJSONP = true;
130.1024 +                        jsonpVarName = p;
130.1025 +                        continue;
130.1026 +                    }
130.1027 +                    body.append(sep);
130.1028 +                    body.append("String ").append(p);
130.1029 +                    sep = ", ";
130.1030 +                }
130.1031 +                if (!skipJSONP) {
130.1032 +                    error(
130.1033 +                        "Name of jsonp attribute ('" + onR.jsonp() + 
130.1034 +                        "') is not used in url attribute '" + onR.url() + "'", e
130.1035 +                    );
130.1036 +                }
130.1037 +                if (dataMirror != null) {
130.1038 +                    body.append(sep).append(dataMirror.toString()).append(" data");
130.1039 +                }
130.1040 +            }
130.1041 +            body.append(") {\n");
130.1042 +            boolean webSocket = onR.method().equals("WebSocket");
130.1043 +            if (webSocket) {
130.1044 +                if (generateWSReceiveBody(body, onR, e, clazz, className, expectsList, modelClass, n, args, urlBefore, jsonpVarName, urlAfter, dataMirror)) {
130.1045 +                    return false;
130.1046 +                }
130.1047 +                body.append("  }\n");
130.1048 +                body.append("  private org.netbeans.html.json.impl.JSON.WS ws_" + e.getSimpleName() + ";\n");
130.1049 +            } else {
130.1050 +                if (generateJSONReceiveBody(body, onR, e, clazz, className, expectsList, modelClass, n, args, urlBefore, jsonpVarName, urlAfter, dataMirror)) {
130.1051 +                    return false;
130.1052 +                }
130.1053 +                body.append("  }\n");
130.1054 +            }
130.1055 +        }
130.1056 +        return true;
130.1057 +    }
130.1058 +
130.1059 +    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) {
130.1060 +        body.append(
130.1061 +            "    class ProcessResult extends org.netbeans.html.json.impl.RcvrJSON {\n" +
130.1062 +            "      @Override\n" +
130.1063 +            "      public void onError(org.netbeans.html.json.impl.RcvrJSON.MsgEvnt ev) {\n" +
130.1064 +            "        Exception value = ev.getException();\n"
130.1065 +            );
130.1066 +        if (onR.onError().isEmpty()) {
130.1067 +            body.append(
130.1068 +                "        value.printStackTrace();\n"
130.1069 +                );
130.1070 +        } else {
130.1071 +            if (!findOnError(e, ((TypeElement)clazz), onR.onError(), className)) {
130.1072 +                return true;
130.1073 +            }
130.1074 +            body.append("        ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
130.1075 +            body.append(className).append(".this, value);\n");
130.1076 +        }
130.1077 +        body.append(
130.1078 +            "      }\n" +
130.1079 +            "      @Override\n" +
130.1080 +            "      public void onMessage(org.netbeans.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
130.1081 +            );
130.1082 +        if (expectsList) {
130.1083 +            body.append(
130.1084 +                "        " + modelClass + "[] arr = new " + modelClass + "[ev.dataSize()];\n"
130.1085 +                );
130.1086 +        } else {
130.1087 +            body.append(
130.1088 +                "        " + modelClass + "[] arr = { null };\n"
130.1089 +                );
130.1090 +        }
130.1091 +        body.append(
130.1092 +            "        ev.dataRead(context, " + modelClass + ".class, arr);\n"
130.1093 +            );
130.1094 +        {
130.1095 +            body.append("        ").append(clazz.getSimpleName()).append(".").append(n).append("(");
130.1096 +            String sep = "";
130.1097 +            for (String arg : args) {
130.1098 +                body.append(sep);
130.1099 +                body.append(arg);
130.1100 +                sep = ", ";
130.1101 +            }
130.1102 +            body.append(");\n");
130.1103 +        }
130.1104 +        body.append(
130.1105 +            "      }\n" +
130.1106 +            "    }\n"
130.1107 +            );
130.1108 +        body.append("    ProcessResult pr = new ProcessResult();\n");
130.1109 +        body.append("    org.netbeans.html.json.impl.JSON.loadJSON(context, pr,\n        ");
130.1110 +        body.append(urlBefore).append(", ");
130.1111 +        if (jsonpVarName != null) {
130.1112 +            body.append(urlAfter);
130.1113 +        } else {
130.1114 +            body.append("null");
130.1115 +        }
130.1116 +        if (!"GET".equals(onR.method()) || dataMirror != null) {
130.1117 +            body.append(", \"").append(onR.method()).append('"');
130.1118 +            if (dataMirror != null) {
130.1119 +                body.append(", data");
130.1120 +            } else {
130.1121 +                body.append(", null");
130.1122 +            }
130.1123 +        } else {
130.1124 +            body.append(", null, null");
130.1125 +        }
130.1126 +        body.append(");\n");
130.1127 +        return false;
130.1128 +    }
130.1129 +    
130.1130 +    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) {
130.1131 +        body.append(
130.1132 +            "    class ProcessResult extends org.netbeans.html.json.impl.RcvrJSON {\n" +
130.1133 +            "      @Override\n" +
130.1134 +            "      public void onOpen(org.netbeans.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
130.1135 +        );
130.1136 +        body.append("        ").append(clazz.getSimpleName()).append(".").append(n).append("(");
130.1137 +        {
130.1138 +            String sep = "";
130.1139 +            for (String arg : args) {
130.1140 +                body.append(sep);
130.1141 +                if (arg.startsWith("arr")) {
130.1142 +                    body.append("null");
130.1143 +                } else {
130.1144 +                    body.append(arg);
130.1145 +                }
130.1146 +                sep = ", ";
130.1147 +            }
130.1148 +        }
130.1149 +        body.append(");\n");
130.1150 +        body.append(
130.1151 +            "      }\n" +
130.1152 +            "      @Override\n" +
130.1153 +            "      public void onError(org.netbeans.html.json.impl.RcvrJSON.MsgEvnt ev) {\n" +
130.1154 +            "        Exception value = ev.getException();\n"
130.1155 +            );
130.1156 +        if (onR.onError().isEmpty()) {
130.1157 +            body.append(
130.1158 +                "        value.printStackTrace();\n"
130.1159 +                );
130.1160 +        } else {
130.1161 +            if (!findOnError(e, ((TypeElement)clazz), onR.onError(), className)) {
130.1162 +                return true;
130.1163 +            }
130.1164 +            body.append("        ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
130.1165 +            body.append(className).append(".this, value);\n");
130.1166 +        }
130.1167 +        body.append(
130.1168 +            "      }\n" +
130.1169 +            "      @Override\n" +
130.1170 +            "      public void onMessage(org.netbeans.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
130.1171 +        );
130.1172 +        if (expectsList) {
130.1173 +            body.append(
130.1174 +                "        " + modelClass + "[] arr = new " + modelClass + "[ev.dataSize()];\n"
130.1175 +                );
130.1176 +        } else {
130.1177 +            body.append(
130.1178 +                "        " + modelClass + "[] arr = { null };\n"
130.1179 +                );
130.1180 +        }
130.1181 +        body.append(
130.1182 +            "        ev.dataRead(context, " + modelClass + ".class, arr);\n"
130.1183 +            );
130.1184 +        {
130.1185 +            body.append("        ").append(clazz.getSimpleName()).append(".").append(n).append("(");
130.1186 +            String sep = "";
130.1187 +            for (String arg : args) {
130.1188 +                body.append(sep);
130.1189 +                body.append(arg);
130.1190 +                sep = ", ";
130.1191 +            }
130.1192 +            body.append(");\n");
130.1193 +        }
130.1194 +        body.append(
130.1195 +            "      }\n"
130.1196 +        );
130.1197 +        if (!onR.onError().isEmpty()) {
130.1198 +            body.append(
130.1199 +                "      @Override\n"
130.1200 +              + "      public void onClose(org.netbeans.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
130.1201 +            );
130.1202 +            body.append("        ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
130.1203 +            body.append(className).append(".this, null);\n");
130.1204 +            body.append(
130.1205 +                "      }\n"
130.1206 +            );
130.1207 +        }
130.1208 +        body.append("    }\n");
130.1209 +        body.append("    if (this.ws_").append(e.getSimpleName()).append(" == null) {\n");
130.1210 +        body.append("      ProcessResult pr = new ProcessResult();\n");
130.1211 +        body.append("      this.ws_").append(e.getSimpleName());
130.1212 +        body.append("= org.netbeans.html.json.impl.JSON.openWS(context, pr,\n        ");
130.1213 +        body.append(urlBefore).append(", data);\n");
130.1214 +        body.append("    } else {\n");
130.1215 +        body.append("      this.ws_").append(e.getSimpleName()).append(".send(context, ").append(urlBefore).append(", data);\n");
130.1216 +        body.append("    }\n");
130.1217 +        return false;
130.1218 +    }
130.1219 +
130.1220 +    private CharSequence wrapParams(
130.1221 +        ExecutableElement ee, String id, String className, String evName, String dataName
130.1222 +    ) {
130.1223 +        TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
130.1224 +        StringBuilder params = new StringBuilder();
130.1225 +        boolean first = true;
130.1226 +        for (VariableElement ve : ee.getParameters()) {
130.1227 +            if (!first) {
130.1228 +                params.append(", ");
130.1229 +            }
130.1230 +            first = false;
130.1231 +            String toCall = null;
130.1232 +            String toFinish = null;
130.1233 +            if (ve.asType() == stringType) {
130.1234 +                if (ve.getSimpleName().contentEquals("id")) {
130.1235 +                    params.append('"').append(id).append('"');
130.1236 +                    continue;
130.1237 +                }
130.1238 +                toCall = "org.netbeans.html.json.impl.JSON.toString(context, ";
130.1239 +            }
130.1240 +            if (ve.asType().getKind() == TypeKind.DOUBLE) {
130.1241 +                toCall = "org.netbeans.html.json.impl.JSON.toNumber(context, ";
130.1242 +                toFinish = ".doubleValue()";
130.1243 +            }
130.1244 +            if (ve.asType().getKind() == TypeKind.INT) {
130.1245 +                toCall = "org.netbeans.html.json.impl.JSON.toNumber(context, ";
130.1246 +                toFinish = ".intValue()";
130.1247 +            }
130.1248 +            if (dataName != null && ve.getSimpleName().contentEquals(dataName) && isModel(ve.asType())) {
130.1249 +                toCall = "org.netbeans.html.json.impl.JSON.toModel(context, " + ve.asType() + ".class, ";
130.1250 +            }
130.1251 +
130.1252 +            if (toCall != null) {
130.1253 +                params.append(toCall);
130.1254 +                if (dataName != null && ve.getSimpleName().contentEquals(dataName)) {
130.1255 +                    params.append(dataName);
130.1256 +                    params.append(", null");
130.1257 +                } else {
130.1258 +                    if (evName == null) {
130.1259 +                        final StringBuilder sb = new StringBuilder();
130.1260 +                        sb.append("Unexpected string parameter name.");
130.1261 +                        if (dataName != null) {
130.1262 +                            sb.append(" Try \"").append(dataName).append("\"");
130.1263 +                        }
130.1264 +                        error(sb.toString(), ee);
130.1265 +                    }
130.1266 +                    params.append(evName);
130.1267 +                    params.append(", \"");
130.1268 +                    params.append(ve.getSimpleName().toString());
130.1269 +                    params.append("\"");
130.1270 +                }
130.1271 +                params.append(")");
130.1272 +                if (toFinish != null) {
130.1273 +                    params.append(toFinish);
130.1274 +                }
130.1275 +                continue;
130.1276 +            }
130.1277 +            String rn = fqn(ve.asType(), ee);
130.1278 +            int last = rn.lastIndexOf('.');
130.1279 +            if (last >= 0) {
130.1280 +                rn = rn.substring(last + 1);
130.1281 +            }
130.1282 +            if (rn.equals(className)) {
130.1283 +                params.append(className).append(".this");
130.1284 +                continue;
130.1285 +            }
130.1286 +            error(
130.1287 +                "The annotated method can only accept " + className + " argument or argument named 'data'",
130.1288 +                ee
130.1289 +            );
130.1290 +        }
130.1291 +        return params;
130.1292 +    }
130.1293 +    
130.1294 +    
130.1295 +    private CharSequence wrapPropName(
130.1296 +        ExecutableElement ee, String className, String propName, String propValue
130.1297 +    ) {
130.1298 +        TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
130.1299 +        StringBuilder params = new StringBuilder();
130.1300 +        boolean first = true;
130.1301 +        for (VariableElement ve : ee.getParameters()) {
130.1302 +            if (!first) {
130.1303 +                params.append(", ");
130.1304 +            }
130.1305 +            first = false;
130.1306 +            if (ve.asType() == stringType) {
130.1307 +                if (propName != null && ve.getSimpleName().contentEquals(propName)) {
130.1308 +                    params.append('"').append(propValue).append('"');
130.1309 +                } else {
130.1310 +                    error("Unexpected string parameter name. Try \"" + propName + "\".", ee);
130.1311 +                }
130.1312 +                continue;
130.1313 +            }
130.1314 +            String rn = fqn(ve.asType(), ee);
130.1315 +            int last = rn.lastIndexOf('.');
130.1316 +            if (last >= 0) {
130.1317 +                rn = rn.substring(last + 1);
130.1318 +            }
130.1319 +            if (rn.equals(className)) {
130.1320 +                params.append(className).append(".this");
130.1321 +                continue;
130.1322 +            }
130.1323 +            error(
130.1324 +                "@OnPrprtChange method can only accept String or " + className + " arguments",
130.1325 +                ee);
130.1326 +        }
130.1327 +        return params;
130.1328 +    }
130.1329 +    
130.1330 +    private boolean isModel(TypeMirror tm) {
130.1331 +        if (tm.getKind() == TypeKind.ERROR) {
130.1332 +            return true;
130.1333 +        }
130.1334 +        final Element e = processingEnv.getTypeUtils().asElement(tm);
130.1335 +        if (e == null) {
130.1336 +            return false;
130.1337 +        }
130.1338 +        for (Element ch : e.getEnclosedElements()) {
130.1339 +            if (ch.getKind() == ElementKind.METHOD) {
130.1340 +                ExecutableElement ee = (ExecutableElement)ch;
130.1341 +                if (ee.getParameters().isEmpty() && ee.getSimpleName().contentEquals("modelFor")) {
130.1342 +                    return true;
130.1343 +                }
130.1344 +            }
130.1345 +        }
130.1346 +        return models.values().contains(e.getSimpleName().toString());
130.1347 +    }
130.1348 +    
130.1349 +    private void writeToString(Prprt[] props, Writer w) throws IOException {
130.1350 +        w.write("  public String toString() {\n");
130.1351 +        w.write("    StringBuilder sb = new StringBuilder();\n");
130.1352 +        w.write("    sb.append('{');\n");
130.1353 +        String sep = "";
130.1354 +        for (Prprt p : props) {
130.1355 +            w.write(sep);
130.1356 +            w.append("    sb.append('\"').append(\"" + p.name() + "\")");
130.1357 +                w.append(".append('\"').append(\":\");\n");
130.1358 +            w.append("    sb.append(org.netbeans.html.json.impl.JSON.toJSON(prop_");
130.1359 +            w.append(p.name()).append("));\n");
130.1360 +            sep =    "    sb.append(',');\n";
130.1361 +        }
130.1362 +        w.write("    sb.append('}');\n");
130.1363 +        w.write("    return sb.toString();\n");
130.1364 +        w.write("  }\n");
130.1365 +    }
130.1366 +    private void writeClone(String className, Prprt[] props, Writer w) throws IOException {
130.1367 +        w.write("  public " + className + " clone() {\n");
130.1368 +        w.write("    return clone(context);\n");
130.1369 +        w.write("  }\n");
130.1370 +        w.write("  private " + className + " clone(net.java.html.BrwsrCtx ctx) {\n");
130.1371 +        w.write("    " + className + " ret = new " + className + "(ctx);\n");
130.1372 +        for (Prprt p : props) {
130.1373 +            if (!p.array()) {
130.1374 +                boolean isModel[] = { false };
130.1375 +                boolean isEnum[] = { false };
130.1376 +                boolean isPrimitive[] = { false };
130.1377 +                checkType(p, isModel, isEnum, isPrimitive);
130.1378 +                if (!isModel[0]) {
130.1379 +                    w.write("    ret.prop_" + p.name() + " = prop_" + p.name() + ";\n");
130.1380 +                    continue;
130.1381 +                }
130.1382 +                w.write("    ret.prop_" + p.name() + " =  prop_" + p.name() + "  == null ? null : prop_" + p.name() + ".clone();\n");
130.1383 +            } else {
130.1384 +                w.write("    ret.prop_" + p.name() + ".cloneAll(ctx, prop_" + p.name() + ");\n");
130.1385 +            }
130.1386 +        }
130.1387 +        
130.1388 +        w.write("    return ret;\n");
130.1389 +        w.write("  }\n");
130.1390 +    }
130.1391 +
130.1392 +    private String inPckName(Element e) {
130.1393 +        StringBuilder sb = new StringBuilder();
130.1394 +        while (e.getKind() != ElementKind.PACKAGE) {
130.1395 +            if (sb.length() == 0) {
130.1396 +                sb.append(e.getSimpleName());
130.1397 +            } else {
130.1398 +                sb.insert(0, '.');
130.1399 +                sb.insert(0, e.getSimpleName());
130.1400 +            }
130.1401 +            e = e.getEnclosingElement();
130.1402 +        }
130.1403 +        return sb.toString();
130.1404 +    }
130.1405 +
130.1406 +    private String fqn(TypeMirror pt, Element relative) {
130.1407 +        if (pt.getKind() == TypeKind.ERROR) {
130.1408 +            final Elements eu = processingEnv.getElementUtils();
130.1409 +            PackageElement pckg = eu.getPackageOf(relative);
130.1410 +            return pckg.getQualifiedName() + "." + pt.toString();
130.1411 +        }
130.1412 +        return pt.toString();
130.1413 +    }
130.1414 +
130.1415 +    private String checkType(Prprt p, boolean[] isModel, boolean[] isEnum, boolean[] isPrimitive) {
130.1416 +        TypeMirror tm;
130.1417 +        try {
130.1418 +            String ret = p.typeName(processingEnv);
130.1419 +            TypeElement e = processingEnv.getElementUtils().getTypeElement(ret);
130.1420 +            if (e == null) {
130.1421 +                isModel[0] = true;
130.1422 +                isEnum[0] = false;
130.1423 +                isPrimitive[0] = false;
130.1424 +                return ret;
130.1425 +            }
130.1426 +            tm = e.asType();
130.1427 +        } catch (MirroredTypeException ex) {
130.1428 +            tm = ex.getTypeMirror();
130.1429 +        }
130.1430 +        tm = processingEnv.getTypeUtils().erasure(tm);
130.1431 +        if (isPrimitive[0] = tm.getKind().isPrimitive()) {
130.1432 +            isEnum[0] = false;
130.1433 +            isModel[0] = false;
130.1434 +            return tm.toString();
130.1435 +        }
130.1436 +        final Element e = processingEnv.getTypeUtils().asElement(tm);
130.1437 +        if (e.getKind() == ElementKind.CLASS && tm.getKind() == TypeKind.ERROR) {
130.1438 +            isModel[0] = true;
130.1439 +            isEnum[0] = false;
130.1440 +            return e.getSimpleName().toString();
130.1441 +        }
130.1442 +        
130.1443 +        final Model m = e == null ? null : e.getAnnotation(Model.class);
130.1444 +        String ret;
130.1445 +        if (m != null) {
130.1446 +            ret = findPkgName(e) + '.' + m.className();
130.1447 +            isModel[0] = true;
130.1448 +            models.put(e, m.className());
130.1449 +        } else if (findModelForMthd(e)) {
130.1450 +            ret = ((TypeElement)e).getQualifiedName().toString();
130.1451 +            isModel[0] = true;
130.1452 +        } else {
130.1453 +            ret = tm.toString();
130.1454 +        }
130.1455 +        TypeMirror enm = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType();
130.1456 +        enm = processingEnv.getTypeUtils().erasure(enm);
130.1457 +        isEnum[0] = processingEnv.getTypeUtils().isSubtype(tm, enm);
130.1458 +        return ret;
130.1459 +    }
130.1460 +    
130.1461 +    private static boolean findModelForMthd(Element clazz) {
130.1462 +        if (clazz == null) {
130.1463 +            return false;
130.1464 +        }
130.1465 +        for (Element e : clazz.getEnclosedElements()) {
130.1466 +            if (e.getKind() == ElementKind.METHOD) {
130.1467 +                ExecutableElement ee = (ExecutableElement)e;
130.1468 +                if (
130.1469 +                    ee.getSimpleName().contentEquals("modelFor") &&
130.1470 +                    ee.getParameters().isEmpty()
130.1471 +                ) {
130.1472 +                    return true;
130.1473 +                }
130.1474 +            }
130.1475 +        }
130.1476 +        return false;
130.1477 +    }
130.1478 +
130.1479 +    private Iterable<String> findParamNames(
130.1480 +        Element e, String url, String jsonParam, StringBuilder... both
130.1481 +    ) {
130.1482 +        List<String> params = new ArrayList<String>();
130.1483 +        int wasJSON = 0;
130.1484 +
130.1485 +        for (int pos = 0; ;) {
130.1486 +            int next = url.indexOf('{', pos);
130.1487 +            if (next == -1) {
130.1488 +                both[wasJSON].append('"')
130.1489 +                    .append(url.substring(pos))
130.1490 +                    .append('"');
130.1491 +                return params;
130.1492 +            }
130.1493 +            int close = url.indexOf('}', next);
130.1494 +            if (close == -1) {
130.1495 +                error("Unbalanced '{' and '}' in " + url, e);
130.1496 +                return params;
130.1497 +            }
130.1498 +            final String paramName = url.substring(next + 1, close);
130.1499 +            params.add(paramName);
130.1500 +            if (paramName.equals(jsonParam) && !jsonParam.isEmpty()) {
130.1501 +                both[wasJSON].append('"')
130.1502 +                    .append(url.substring(pos, next))
130.1503 +                    .append('"');
130.1504 +                wasJSON = 1;
130.1505 +            } else {
130.1506 +                both[wasJSON].append('"')
130.1507 +                    .append(url.substring(pos, next))
130.1508 +                    .append("\" + ").append(paramName).append(" + ");
130.1509 +            }
130.1510 +            pos = close + 1;
130.1511 +        }
130.1512 +    }
130.1513 +
130.1514 +    private static Prprt findPrprt(Prprt[] properties, String propName) {
130.1515 +        for (Prprt p : properties) {
130.1516 +            if (propName.equals(p.name())) {
130.1517 +                return p;
130.1518 +            }
130.1519 +        }
130.1520 +        return null;
130.1521 +    }
130.1522 +
130.1523 +    private boolean isPrimitive(String type) {
130.1524 +        return 
130.1525 +            "int".equals(type) ||
130.1526 +            "double".equals(type) ||
130.1527 +            "long".equals(type) ||
130.1528 +            "short".equals(type) ||
130.1529 +            "byte".equals(type) ||
130.1530 +            "char".equals(type) ||
130.1531 +            "boolean".equals(type) ||
130.1532 +            "float".equals(type);
130.1533 +    }
130.1534 +
130.1535 +    private static Collection<String> findDerivedFrom(Map<String, Collection<String>> propsDeps, String derivedProp) {
130.1536 +        Set<String> names = new HashSet<String>();
130.1537 +        for (Map.Entry<String, Collection<String>> e : propsDeps.entrySet()) {
130.1538 +            if (e.getValue().contains(derivedProp)) {
130.1539 +                names.add(e.getKey());
130.1540 +            }
130.1541 +        }
130.1542 +        return names;
130.1543 +    }
130.1544 +    
130.1545 +    private Prprt[] createProps(Element e, Property[] arr) {
130.1546 +        Prprt[] ret = Prprt.wrap(processingEnv, e, arr);
130.1547 +        Prprt[] prev = verify.put(e, ret);
130.1548 +        if (prev != null) {
130.1549 +            error("Two sets of properties for ", e);
130.1550 +        }
130.1551 +        return ret;
130.1552 +    }
130.1553 +    
130.1554 +    private static String strip(String s) {
130.1555 +        int indx = s.indexOf("__");
130.1556 +        if (indx >= 0) {
130.1557 +            return s.substring(0, indx);
130.1558 +        } else {
130.1559 +            return s;
130.1560 +        }
130.1561 +    }
130.1562 +
130.1563 +    private String findDataSpecified(ExecutableElement e, OnReceive onR) {
130.1564 +        try {
130.1565 +            return onR.data().getName();
130.1566 +        } catch (MirroredTypeException ex) {
130.1567 +            final TypeMirror tm = ex.getTypeMirror();
130.1568 +            String name;
130.1569 +            final Element te = processingEnv.getTypeUtils().asElement(tm);
130.1570 +            if (te.getKind() == ElementKind.CLASS && tm.getKind() == TypeKind.ERROR) {
130.1571 +                name = te.getSimpleName().toString();
130.1572 +            } else {
130.1573 +                name = tm.toString();
130.1574 +            }
130.1575 +            return "java.lang.Object".equals(name) ? null : name;
130.1576 +        } catch (Exception ex) {
130.1577 +            // fallback
130.1578 +        }
130.1579 +        
130.1580 +        AnnotationMirror found = null;
130.1581 +        for (AnnotationMirror am : e.getAnnotationMirrors()) {
130.1582 +            if (am.getAnnotationType().toString().equals(OnReceive.class.getName())) {
130.1583 +                found = am;
130.1584 +            }
130.1585 +        }
130.1586 +        if (found == null) {
130.1587 +            return null;
130.1588 +        }
130.1589 +        
130.1590 +        for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : found.getElementValues().entrySet()) {
130.1591 +            ExecutableElement ee = entry.getKey();
130.1592 +            AnnotationValue av = entry.getValue();
130.1593 +            if (ee.getSimpleName().contentEquals("data")) {
130.1594 +                List<? extends Object> values = getAnnoValues(processingEnv, e, found);
130.1595 +                for (Object v : values) {
130.1596 +                    String sv = v.toString();
130.1597 +                    if (sv.startsWith("data = ") && sv.endsWith(".class")) {
130.1598 +                        return sv.substring(7, sv.length() - 6);
130.1599 +                    }
130.1600 +                }
130.1601 +                return "error";
130.1602 +            }
130.1603 +        }
130.1604 +        return null;
130.1605 +    }
130.1606 +
130.1607 +    static List<? extends Object> getAnnoValues(ProcessingEnvironment pe, Element e, AnnotationMirror am) {
130.1608 +        try {
130.1609 +            Class<?> trees = Class.forName("com.sun.tools.javac.api.JavacTrees");
130.1610 +            Method m = trees.getMethod("instance", ProcessingEnvironment.class);
130.1611 +            Object instance = m.invoke(null, pe);
130.1612 +            m = instance.getClass().getMethod("getPath", Element.class, AnnotationMirror.class);
130.1613 +            Object path = m.invoke(instance, e, am);
130.1614 +            m = path.getClass().getMethod("getLeaf");
130.1615 +            Object leaf = m.invoke(path);
130.1616 +            m = leaf.getClass().getMethod("getArguments");
130.1617 +            return (List) m.invoke(leaf);
130.1618 +        } catch (Exception ex) {
130.1619 +            return Collections.emptyList();
130.1620 +        }
130.1621 +    }
130.1622 +
130.1623 +    private static class Prprt {
130.1624 +        private final Element e;
130.1625 +        private final AnnotationMirror tm;
130.1626 +        private final Property p;
130.1627 +
130.1628 +        public Prprt(Element e, AnnotationMirror tm, Property p) {
130.1629 +            this.e = e;
130.1630 +            this.tm = tm;
130.1631 +            this.p = p;
130.1632 +        }
130.1633 +        
130.1634 +        String name() {
130.1635 +            return p.name();
130.1636 +        }
130.1637 +        
130.1638 +        boolean array() {
130.1639 +            return p.array();
130.1640 +        }
130.1641 +
130.1642 +        String typeName(ProcessingEnvironment env) {
130.1643 +            RuntimeException ex;
130.1644 +            try {
130.1645 +                return p.type().getName();
130.1646 +            } catch (IncompleteAnnotationException e) {
130.1647 +                ex = e;
130.1648 +            } catch (AnnotationTypeMismatchException e) {
130.1649 +                ex = e;
130.1650 +            }
130.1651 +            for (Object v : getAnnoValues(env, e, tm)) {
130.1652 +                String s = v.toString().replace(" ", "");
130.1653 +                if (s.startsWith("type=") && s.endsWith(".class")) {
130.1654 +                    return s.substring(5, s.length() - 6);
130.1655 +                }
130.1656 +            }
130.1657 +            throw ex;
130.1658 +        }
130.1659 +        
130.1660 +        
130.1661 +        static Prprt[] wrap(ProcessingEnvironment pe, Element e, Property[] arr) {
130.1662 +            if (arr.length == 0) {
130.1663 +                return new Prprt[0];
130.1664 +            }
130.1665 +            
130.1666 +            if (e.getKind() != ElementKind.CLASS) {
130.1667 +                throw new IllegalStateException("" + e.getKind());
130.1668 +            }
130.1669 +            TypeElement te = (TypeElement)e;
130.1670 +            List<? extends AnnotationValue> val = null;
130.1671 +            for (AnnotationMirror an : te.getAnnotationMirrors()) {
130.1672 +                for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : an.getElementValues().entrySet()) {
130.1673 +                    if (entry.getKey().getSimpleName().contentEquals("properties")) {
130.1674 +                        val = (List)entry.getValue().getValue();
130.1675 +                        break;
130.1676 +                    }
130.1677 +                }
130.1678 +            }
130.1679 +            if (val == null || val.size() != arr.length) {
130.1680 +                pe.getMessager().printMessage(Diagnostic.Kind.ERROR, "" + val, e);
130.1681 +                return new Prprt[0];
130.1682 +            }
130.1683 +            Prprt[] ret = new Prprt[arr.length];
130.1684 +            BIG: for (int i = 0; i < ret.length; i++) {
130.1685 +                AnnotationMirror am = (AnnotationMirror)val.get(i).getValue();
130.1686 +                ret[i] = new Prprt(e, am, arr[i]);
130.1687 +                
130.1688 +            }
130.1689 +            return ret;
130.1690 +        }
130.1691 +    }
130.1692 +
130.1693 +    @Override
130.1694 +    public Iterable<? extends Completion> getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) {
130.1695 +        final Level l = Level.FINE;
130.1696 +        LOG.log(l, " element: {0}", element);
130.1697 +        LOG.log(l, " annotation: {0}", annotation);
130.1698 +        LOG.log(l, " member: {0}", member);
130.1699 +        LOG.log(l, " userText: {0}", userText);
130.1700 +        LOG.log(l, "str: {0}", annotation.getAnnotationType().toString());
130.1701 +        if (annotation.getAnnotationType().toString().equals(OnReceive.class.getName())) {
130.1702 +            if (member.getSimpleName().contentEquals("method")) {
130.1703 +                return Arrays.asList(
130.1704 +                    methodOf("GET"),
130.1705 +                    methodOf("POST"),
130.1706 +                    methodOf("PUT"),
130.1707 +                    methodOf("DELETE"),
130.1708 +                    methodOf("HEAD"),
130.1709 +                    methodOf("WebSocket")
130.1710 +                );
130.1711 +            }
130.1712 +        }
130.1713 +        
130.1714 +        return super.getCompletions(element, annotation, member, userText);
130.1715 +    }
130.1716 +    
130.1717 +    private static final Completion methodOf(String method) {
130.1718 +        ResourceBundle rb = ResourceBundle.getBundle("org.netbeans.html.json.impl.Bundle");
130.1719 +        return Completions.of('"' + method + '"', rb.getString("MSG_Completion_" + method));
130.1720 +    }
130.1721 +    
130.1722 +    private boolean findOnError(ExecutableElement errElem, TypeElement te, String name, String className) {
130.1723 +        String err = null;
130.1724 +        METHODS:
130.1725 +        for (Element e : te.getEnclosedElements()) {
130.1726 +            if (e.getKind() != ElementKind.METHOD) {
130.1727 +                continue;
130.1728 +            }
130.1729 +            if (!e.getSimpleName().contentEquals(name)) {
130.1730 +                continue;
130.1731 +            }
130.1732 +            if (!e.getModifiers().contains(Modifier.STATIC)) {
130.1733 +                errElem = (ExecutableElement) e;
130.1734 +                err = "Would have to be static";
130.1735 +                continue;
130.1736 +            }
130.1737 +            ExecutableElement ee = (ExecutableElement) e;
130.1738 +            TypeMirror excType = processingEnv.getElementUtils().getTypeElement(Exception.class.getName()).asType();
130.1739 +            final List<? extends VariableElement> params = ee.getParameters();
130.1740 +            boolean error = false;
130.1741 +            if (params.size() != 2) {
130.1742 +                error = true;
130.1743 +            } else {
130.1744 +                String firstType = params.get(0).asType().toString();
130.1745 +                int lastDot = firstType.lastIndexOf('.');
130.1746 +                if (lastDot != -1) {
130.1747 +                    firstType = firstType.substring(lastDot + 1);
130.1748 +                }
130.1749 +                if (!firstType.equals(className)) {
130.1750 +                    error = true;
130.1751 +                }
130.1752 +                if (!processingEnv.getTypeUtils().isAssignable(excType, params.get(1).asType())) {
130.1753 +                    error = true;
130.1754 +                }
130.1755 +            }
130.1756 +            if (error) {
130.1757 +                errElem = (ExecutableElement) e;
130.1758 +                err = "Error method first argument needs to be " + className + " and second Exception";
130.1759 +                continue;
130.1760 +            }
130.1761 +            return true;
130.1762 +        }
130.1763 +        if (err == null) {
130.1764 +            err = "Cannot find " + name + "(" + className + ", Exception) method in this class";
130.1765 +        }
130.1766 +        error(err, errElem);
130.1767 +        return false;
130.1768 +    }
130.1769 +    
130.1770 +}
   131.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   131.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/PropertyBindingAccessor.java	Mon Dec 16 17:16:40 2013 +0100
   131.3 @@ -0,0 +1,135 @@
   131.4 +/**
   131.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   131.6 + *
   131.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   131.8 + *
   131.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  131.10 + * Other names may be trademarks of their respective owners.
  131.11 + *
  131.12 + * The contents of this file are subject to the terms of either the GNU
  131.13 + * General Public License Version 2 only ("GPL") or the Common
  131.14 + * Development and Distribution License("CDDL") (collectively, the
  131.15 + * "License"). You may not use this file except in compliance with the
  131.16 + * License. You can obtain a copy of the License at
  131.17 + * http://www.netbeans.org/cddl-gplv2.html
  131.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  131.19 + * specific language governing permissions and limitations under the
  131.20 + * License.  When distributing the software, include this License Header
  131.21 + * Notice in each file and include the License file at
  131.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  131.23 + * particular file as subject to the "Classpath" exception as provided
  131.24 + * by Oracle in the GPL Version 2 section of the License file that
  131.25 + * accompanied this code. If applicable, add the following below the
  131.26 + * License Header, with the fields enclosed by brackets [] replaced by
  131.27 + * your own identifying information:
  131.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  131.29 + *
  131.30 + * Contributor(s):
  131.31 + *
  131.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  131.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  131.34 + *
  131.35 + * If you wish your version of this file to be governed by only the CDDL
  131.36 + * or only the GPL Version 2, indicate your decision by adding
  131.37 + * "[Contributor] elects to include this software in this distribution
  131.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  131.39 + * single choice of license, a recipient has the option to distribute
  131.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  131.41 + * to extend the choice of license to its licensees as provided above.
  131.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  131.43 + * Version 2 license, then the option applies only if the new code is
  131.44 + * made subject to such option by the copyright holder.
  131.45 + */
  131.46 +package org.netbeans.html.json.impl;
  131.47 +
  131.48 +import net.java.html.BrwsrCtx;
  131.49 +import org.apidesign.html.json.spi.FunctionBinding;
  131.50 +import org.apidesign.html.json.spi.JSONCall;
  131.51 +import org.apidesign.html.json.spi.PropertyBinding;
  131.52 +
  131.53 +/**
  131.54 + *
  131.55 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  131.56 + */
  131.57 +public abstract class PropertyBindingAccessor {
  131.58 +    private static PropertyBindingAccessor DEFAULT;
  131.59 +
  131.60 +    protected PropertyBindingAccessor() {
  131.61 +        if (DEFAULT != null) throw new IllegalStateException();
  131.62 +        DEFAULT = this;
  131.63 +    }
  131.64 +    
  131.65 +    static {
  131.66 +        JSON.initClass(PropertyBinding.class);
  131.67 +    }
  131.68 +
  131.69 +    protected abstract <M> PropertyBinding newBinding(PBData<M> d);
  131.70 +    protected abstract <M> FunctionBinding newFunction(FBData<M> d);
  131.71 +    protected abstract JSONCall newCall(
  131.72 +        BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter,
  131.73 +        String method, Object data
  131.74 +    );
  131.75 +
  131.76 +    
  131.77 +    static <M> PropertyBinding create(PBData<M> d) {
  131.78 +        return DEFAULT.newBinding(d);
  131.79 +    }
  131.80 +    static <M> FunctionBinding createFunction(FBData<M> d) {
  131.81 +        return DEFAULT.newFunction(d);
  131.82 +    }
  131.83 +    static JSONCall createCall(
  131.84 +        BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter, 
  131.85 +        String method, Object data
  131.86 +    ) {
  131.87 +        return DEFAULT.newCall(ctx, callback, urlBefore, urlAfter, method, data);
  131.88 +    }
  131.89 +
  131.90 +    public static final class PBData<M> {
  131.91 +        public final String name;
  131.92 +        public final boolean readOnly;
  131.93 +        private final M model;
  131.94 +        private final SetAndGet<M> access;
  131.95 +        private final Bindings<?> bindings;
  131.96 +
  131.97 +        public PBData(Bindings<?> bindings, String name, M model, SetAndGet<M> access, boolean readOnly) {
  131.98 +            this.bindings = bindings;
  131.99 +            this.name = name;
 131.100 +            this.model = model;
 131.101 +            this.access = access;
 131.102 +            this.readOnly = readOnly;
 131.103 +        }
 131.104 +
 131.105 +        public void setValue(Object v) {
 131.106 +            access.setValue(model, v);
 131.107 +        }
 131.108 +
 131.109 +        public Object getValue() {
 131.110 +            return access.getValue(model);
 131.111 +        }
 131.112 +
 131.113 +        public boolean isReadOnly() {
 131.114 +            return readOnly;
 131.115 +        }
 131.116 +
 131.117 +        public Bindings getBindings() {
 131.118 +            return bindings;
 131.119 +        }
 131.120 +    } // end of PBData
 131.121 +    
 131.122 +    public static final class FBData<M> {
 131.123 +        public final String name;
 131.124 +        private final M model;
 131.125 +        private final Callback<M> access;
 131.126 +
 131.127 +        public FBData(String name, M model, Callback<M> access) {
 131.128 +            this.name = name;
 131.129 +            this.model = model;
 131.130 +            this.access = access;
 131.131 +        }
 131.132 +
 131.133 +
 131.134 +        public void call(Object data, Object ev) {
 131.135 +            access.call(model, data, ev);
 131.136 +        }
 131.137 +    } // end of FBData
 131.138 +}
   132.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   132.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/RcvrJSON.java	Mon Dec 16 17:16:40 2013 +0100
   132.3 @@ -0,0 +1,149 @@
   132.4 +/**
   132.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   132.6 + *
   132.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   132.8 + *
   132.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  132.10 + * Other names may be trademarks of their respective owners.
  132.11 + *
  132.12 + * The contents of this file are subject to the terms of either the GNU
  132.13 + * General Public License Version 2 only ("GPL") or the Common
  132.14 + * Development and Distribution License("CDDL") (collectively, the
  132.15 + * "License"). You may not use this file except in compliance with the
  132.16 + * License. You can obtain a copy of the License at
  132.17 + * http://www.netbeans.org/cddl-gplv2.html
  132.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  132.19 + * specific language governing permissions and limitations under the
  132.20 + * License.  When distributing the software, include this License Header
  132.21 + * Notice in each file and include the License file at
  132.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  132.23 + * particular file as subject to the "Classpath" exception as provided
  132.24 + * by Oracle in the GPL Version 2 section of the License file that
  132.25 + * accompanied this code. If applicable, add the following below the
  132.26 + * License Header, with the fields enclosed by brackets [] replaced by
  132.27 + * your own identifying information:
  132.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  132.29 + *
  132.30 + * Contributor(s):
  132.31 + *
  132.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  132.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  132.34 + *
  132.35 + * If you wish your version of this file to be governed by only the CDDL
  132.36 + * or only the GPL Version 2, indicate your decision by adding
  132.37 + * "[Contributor] elects to include this software in this distribution
  132.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  132.39 + * single choice of license, a recipient has the option to distribute
  132.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  132.41 + * to extend the choice of license to its licensees as provided above.
  132.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  132.43 + * Version 2 license, then the option applies only if the new code is
  132.44 + * made subject to such option by the copyright holder.
  132.45 + */
  132.46 +package org.netbeans.html.json.impl;
  132.47 +
  132.48 +import net.java.html.BrwsrCtx;
  132.49 +
  132.50 +/** Super type for those who wish to receive JSON messages.
  132.51 + *
  132.52 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  132.53 + */
  132.54 +public abstract class RcvrJSON {
  132.55 +    protected void onOpen(MsgEvnt msg) {}
  132.56 +    protected abstract void onMessage(MsgEvnt msg);
  132.57 +    protected void onClose(MsgEvnt msg) {}
  132.58 +    protected abstract void onError(MsgEvnt msg);
  132.59 +    
  132.60 +    public abstract static class MsgEvnt {
  132.61 +        MsgEvnt() {
  132.62 +        }
  132.63 +        
  132.64 +        public Throwable getError() {
  132.65 +            return null;
  132.66 +        }
  132.67 +        
  132.68 +        public final Exception getException() {
  132.69 +            Throwable t = getError();
  132.70 +            if (t instanceof Exception) {
  132.71 +                return (Exception)t;
  132.72 +            }
  132.73 +            if (t == null) {
  132.74 +                return null;
  132.75 +            }
  132.76 +            return new Exception(t);
  132.77 +        }
  132.78 +        
  132.79 +        public int dataSize() {
  132.80 +            return -1;
  132.81 +        }
  132.82 +        
  132.83 +        public <Data> void dataRead(BrwsrCtx ctx, Class<? extends Data> type, Data[] fillTheArray) {
  132.84 +        }
  132.85 +
  132.86 +        public abstract void dispatch(RcvrJSON r);
  132.87 +        
  132.88 +        public static MsgEvnt createError(final Throwable t) {
  132.89 +            return new MsgEvnt() {
  132.90 +                @Override
  132.91 +                public Throwable getError() {
  132.92 +                    return t;
  132.93 +                }
  132.94 +
  132.95 +                @Override
  132.96 +                public void dispatch(RcvrJSON r) {
  132.97 +                    r.onError(this);
  132.98 +                }
  132.99 +            };
 132.100 +        }
 132.101 +        
 132.102 +        public static MsgEvnt createMessage(final Object value) {
 132.103 +            return new MsgEvnt() {
 132.104 +                @Override
 132.105 +                public int dataSize() {
 132.106 +                    if (value instanceof Object[]) {
 132.107 +                        return ((Object[])value).length;
 132.108 +                    } else {
 132.109 +                        return 1;
 132.110 +                    }
 132.111 +                }
 132.112 +                
 132.113 +                @Override
 132.114 +                public <Data> void dataRead(BrwsrCtx context, Class<? extends Data> type, Data[] arr) {
 132.115 +                    if (value instanceof Object[]) {
 132.116 +                        Object[] data = ((Object[]) value);
 132.117 +                        for (int i = 0; i < data.length && i < arr.length; i++) {
 132.118 +                            arr[i] = org.netbeans.html.json.impl.JSON.read(context, type, data[i]);
 132.119 +                        }
 132.120 +                    } else {
 132.121 +                        if (arr.length > 0) {
 132.122 +                            arr[0] = org.netbeans.html.json.impl.JSON.read(context, type, value);
 132.123 +                        }
 132.124 +                    }
 132.125 +                }
 132.126 +                
 132.127 +                @Override
 132.128 +                public void dispatch(RcvrJSON r) {
 132.129 +                    r.onMessage(this);
 132.130 +                }
 132.131 +            };
 132.132 +        }
 132.133 +        
 132.134 +        public static MsgEvnt createOpen() {
 132.135 +            return new MsgEvnt() {
 132.136 +                @Override
 132.137 +                public void dispatch(RcvrJSON r) {
 132.138 +                    r.onOpen(this);
 132.139 +                }
 132.140 +            };
 132.141 +        }
 132.142 +
 132.143 +        public static MsgEvnt createClose() {
 132.144 +            return new MsgEvnt() {
 132.145 +                @Override
 132.146 +                public void dispatch(RcvrJSON r) {
 132.147 +                    r.onClose(this);
 132.148 +                }
 132.149 +            };
 132.150 +        }
 132.151 +    } // end MsgEvnt
 132.152 +}
   133.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   133.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/SetAndGet.java	Mon Dec 16 17:16:40 2013 +0100
   133.3 @@ -0,0 +1,54 @@
   133.4 +/**
   133.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   133.6 + *
   133.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   133.8 + *
   133.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  133.10 + * Other names may be trademarks of their respective owners.
  133.11 + *
  133.12 + * The contents of this file are subject to the terms of either the GNU
  133.13 + * General Public License Version 2 only ("GPL") or the Common
  133.14 + * Development and Distribution License("CDDL") (collectively, the
  133.15 + * "License"). You may not use this file except in compliance with the
  133.16 + * License. You can obtain a copy of the License at
  133.17 + * http://www.netbeans.org/cddl-gplv2.html
  133.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  133.19 + * specific language governing permissions and limitations under the
  133.20 + * License.  When distributing the software, include this License Header
  133.21 + * Notice in each file and include the License file at
  133.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  133.23 + * particular file as subject to the "Classpath" exception as provided
  133.24 + * by Oracle in the GPL Version 2 section of the License file that
  133.25 + * accompanied this code. If applicable, add the following below the
  133.26 + * License Header, with the fields enclosed by brackets [] replaced by
  133.27 + * your own identifying information:
  133.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  133.29 + *
  133.30 + * Contributor(s):
  133.31 + *
  133.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  133.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  133.34 + *
  133.35 + * If you wish your version of this file to be governed by only the CDDL
  133.36 + * or only the GPL Version 2, indicate your decision by adding
  133.37 + * "[Contributor] elects to include this software in this distribution
  133.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  133.39 + * single choice of license, a recipient has the option to distribute
  133.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  133.41 + * to extend the choice of license to its licensees as provided above.
  133.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  133.43 + * Version 2 license, then the option applies only if the new code is
  133.44 + * made subject to such option by the copyright holder.
  133.45 + */
  133.46 +package org.netbeans.html.json.impl;
  133.47 +
  133.48 +import org.apidesign.html.json.spi.PropertyBinding;
  133.49 +
  133.50 +/** A way to implement a {@link PropertyBinding}.
  133.51 + *
  133.52 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  133.53 + */
  133.54 +public interface SetAndGet<Data> {
  133.55 +    public void setValue(Data data, Object value);
  133.56 +    public Object getValue(Data data);
  133.57 +}
   134.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   134.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/WrapperObject.java	Mon Dec 16 17:16:40 2013 +0100
   134.3 @@ -0,0 +1,82 @@
   134.4 +/**
   134.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   134.6 + *
   134.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   134.8 + *
   134.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  134.10 + * Other names may be trademarks of their respective owners.
  134.11 + *
  134.12 + * The contents of this file are subject to the terms of either the GNU
  134.13 + * General Public License Version 2 only ("GPL") or the Common
  134.14 + * Development and Distribution License("CDDL") (collectively, the
  134.15 + * "License"). You may not use this file except in compliance with the
  134.16 + * License. You can obtain a copy of the License at
  134.17 + * http://www.netbeans.org/cddl-gplv2.html
  134.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  134.19 + * specific language governing permissions and limitations under the
  134.20 + * License.  When distributing the software, include this License Header
  134.21 + * Notice in each file and include the License file at
  134.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  134.23 + * particular file as subject to the "Classpath" exception as provided
  134.24 + * by Oracle in the GPL Version 2 section of the License file that
  134.25 + * accompanied this code. If applicable, add the following below the
  134.26 + * License Header, with the fields enclosed by brackets [] replaced by
  134.27 + * your own identifying information:
  134.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  134.29 + *
  134.30 + * Contributor(s):
  134.31 + *
  134.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  134.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  134.34 + *
  134.35 + * If you wish your version of this file to be governed by only the CDDL
  134.36 + * or only the GPL Version 2, indicate your decision by adding
  134.37 + * "[Contributor] elects to include this software in this distribution
  134.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  134.39 + * single choice of license, a recipient has the option to distribute
  134.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  134.41 + * to extend the choice of license to its licensees as provided above.
  134.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  134.43 + * Version 2 license, then the option applies only if the new code is
  134.44 + * made subject to such option by the copyright holder.
  134.45 + */
  134.46 +package org.netbeans.html.json.impl;
  134.47 +
  134.48 +import java.util.Collection;
  134.49 +import org.netbeans.html.json.impl.PropertyBindingAccessor.PBData;
  134.50 +
  134.51 +/** A way to extract real object from a model classes.
  134.52 + *
  134.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  134.54 + */
  134.55 +public final class WrapperObject {
  134.56 +    private Object ko;
  134.57 +    
  134.58 +    private WrapperObject() {
  134.59 +    }
  134.60 +    
  134.61 +    public void setRealObject(Object ko) {
  134.62 +        this.ko = ko;
  134.63 +    }
  134.64 +    
  134.65 +    public static Object find(Object object) {
  134.66 +        return find(object, null);
  134.67 +    }
  134.68 +    
  134.69 +    public static Object find(Object object, Bindings model) {
  134.70 +        if (object == null) {
  134.71 +            return null;
  134.72 +        }
  134.73 +        
  134.74 +        if (object instanceof JSONList) {
  134.75 +            return ((JSONList<?>)object).koData();
  134.76 +        }
  134.77 +        if (object instanceof Collection) {
  134.78 +            return JSONList.koData((Collection<?>)object, model);
  134.79 +        }
  134.80 +        
  134.81 +        WrapperObject ro = new WrapperObject();
  134.82 +        object.equals(ro);
  134.83 +        return ro.ko;
  134.84 +    }
  134.85 +}
   135.1 --- a/json/src/main/resources/org/apidesign/html/json/impl/Bundle.properties	Mon Dec 16 17:16:02 2013 +0100
   135.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   135.3 @@ -1,75 +0,0 @@
   135.4 -#
   135.5 -# HTML via Java(tm) Language Bindings
   135.6 -# Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   135.7 -#
   135.8 -# This program is free software: you can redistribute it and/or modify
   135.9 -# it under the terms of the GNU General Public License as published by
  135.10 -# the Free Software Foundation, version 2 of the License.
  135.11 -#
  135.12 -# This program is distributed in the hope that it will be useful,
  135.13 -# but WITHOUT ANY WARRANTY; without even the implied warranty of
  135.14 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  135.15 -# GNU General Public License for more details. apidesign.org
  135.16 -# designates this particular file as subject to the
  135.17 -# "Classpath" exception as provided by apidesign.org
  135.18 -# in the License file that accompanied this code.
  135.19 -#
  135.20 -# You should have received a copy of the GNU General Public License
  135.21 -# along with this program. Look for COPYING file in the top folder.
  135.22 -# If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  135.23 -#
  135.24 -
  135.25 -MSG_Completion_GET=The GET method means retrieve whatever information \
  135.26 - (in the form of an entity) is identified by the Request-URI. \
  135.27 - If the Request-URI refers to a data-producing process, \
  135.28 - it is the produced data which shall be returned as the entity in \
  135.29 - the response and not the source text of the process, \
  135.30 - unless that text happens to be the output of the process.
  135.31 -
  135.32 -MSG_Completion_HEAD=The HEAD method is identical to GET except that the server \
  135.33 - MUST NOT return a message-body in the response. The metainformation \
  135.34 - contained in the HTTP headers in response to a HEAD request SHOULD be \
  135.35 - identical to the information sent in response to a GET request. \
  135.36 - This method can be used for obtaining metainformation about the entity implied \
  135.37 - by the request without transferring the entity-body itself. \
  135.38 - This method is often used for testing hypertext links for validity, \
  135.39 - accessibility, and recent modification.
  135.40 -
  135.41 -MSG_Completion_POST=The POST method is used to request that the origin server \
  135.42 - accept the entity enclosed in the request as a new subordinate of the resource \
  135.43 - identified by the Request-URI in the Request-Line. POST is designed to allow \
  135.44 - a uniform method to cover annotation of existing resources,\ 
  135.45 - posting a message to a bulletin board, newsgroup, mailing list, or similar \
  135.46 - group of articles, providing a block of data, such as the result of submitting a \
  135.47 - form, to a data-handling process or extending a database through an append operation. \
  135.48 - The actual function performed by the POST method is determined by the server \
  135.49 - and is usually dependent on the Request-URI. The posted entity is subordinate \
  135.50 - to that URI in the same way that a file is subordinate to a directory containing it, \
  135.51 - a news article is subordinate to a newsgroup to which it is posted, \
  135.52 - or a record is subordinate to a database.
  135.53 -
  135.54 -MSG_Completion_PUT=The PUT method requests that the enclosed entity be stored \
  135.55 - under the supplied Request-URI. If the Request-URI refers to an already \
  135.56 - existing resource, the enclosed entity SHOULD be considered as a modified \
  135.57 - version of the one residing on the origin server. If the Request-URI does \
  135.58 - not point to an existing resource, and that URI is capable of being defined \
  135.59 - as a new resource by the requesting user agent, the origin server can \
  135.60 - create the resource with that URI. If a new resource is created, the origin \
  135.61 - server MUST inform the user agent via the 201 (Created) response. \
  135.62 - If an existing resource is modified, either the 200 (OK) or 204 (No Content) \
  135.63 - response codes SHOULD be sent to indicate successful completion of the request. \
  135.64 - If the resource could not be created or modified with the Request-URI, an \
  135.65 - appropriate error response SHOULD be given that reflects the nature of the problem. \
  135.66 - The recipient of the entity MUST NOT ignore any Content-* (e.g. Content-Range) \
  135.67 - headers that it does not understand or implement and MUST return \
  135.68 - a 501 (Not Implemented) response in such cases.
  135.69 -
  135.70 -MSG_Completion_DELETE=The DELETE method requests that the origin server delete \
  135.71 - the resource identified by the Request-URI. This method MAY be overridden \
  135.72 - by human intervention (or other means) on the origin server. The client \
  135.73 - cannot be guaranteed that the operation has been carried out, even if \
  135.74 - the status code returned from the origin server indicates that the action \
  135.75 - has been completed successfully. However, the server SHOULD NOT indicate \
  135.76 - success unless, at the time the response is given, it intends to delete \
  135.77 - the resource or move it to an inaccessible location.
  135.78 -
   136.1 --- a/json/src/main/resources/org/apidesign/html/json/spi/package.html	Mon Dec 16 17:16:02 2013 +0100
   136.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   136.3 @@ -1,37 +0,0 @@
   136.4 -<!--
   136.5 -
   136.6 -    HTML via Java(tm) Language Bindings
   136.7 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   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 -
  136.13 -    This program is distributed in the hope that it will be useful,
  136.14 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
  136.15 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  136.16 -    GNU General Public License for more details. apidesign.org
  136.17 -    designates this particular file as subject to the
  136.18 -    "Classpath" exception as provided by apidesign.org
  136.19 -    in the License file that accompanied this code.
  136.20 -
  136.21 -    You should have received a copy of the GNU General Public License
  136.22 -    along with this program. Look for COPYING file in the top folder.
  136.23 -    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  136.24 -
  136.25 --->
  136.26 -<!DOCTYPE html>
  136.27 -<html>
  136.28 -    <head>
  136.29 -        <title></title>
  136.30 -        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  136.31 -    </head>
  136.32 -    <body>
  136.33 -        <div>Implement 
  136.34 -            <a href="Technology.html">Technology</a> and
  136.35 -            <a href="Transfer.html">Transfer</a> and use 
  136.36 -            <a href="ContextBuilder.html">ContextBuilder</a> to create an instance
  136.37 -            of <code>Context</code> representing your technology.
  136.38 -        </div>
  136.39 -    </body>
  136.40 -</html>
   137.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   137.2 +++ b/json/src/main/resources/org/netbeans/html/json/impl/Bundle.properties	Mon Dec 16 17:16:40 2013 +0100
   137.3 @@ -0,0 +1,97 @@
   137.4 +#
   137.5 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   137.6 +#
   137.7 +# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   137.8 +#
   137.9 +# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  137.10 +# Other names may be trademarks of their respective owners.
  137.11 +#
  137.12 +# The contents of this file are subject to the terms of either the GNU
  137.13 +# General Public License Version 2 only ("GPL") or the Common
  137.14 +# Development and Distribution License("CDDL") (collectively, the
  137.15 +# "License"). You may not use this file except in compliance with the
  137.16 +# License. You can obtain a copy of the License at
  137.17 +# http://www.netbeans.org/cddl-gplv2.html
  137.18 +# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  137.19 +# specific language governing permissions and limitations under the
  137.20 +# License.  When distributing the software, include this License Header
  137.21 +# Notice in each file and include the License file at
  137.22 +# nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  137.23 +# particular file as subject to the "Classpath" exception as provided
  137.24 +# by Oracle in the GPL Version 2 section of the License file that
  137.25 +# accompanied this code. If applicable, add the following below the
  137.26 +# License Header, with the fields enclosed by brackets [] replaced by
  137.27 +# your own identifying information:
  137.28 +# "Portions Copyrighted [year] [name of copyright owner]"
  137.29 +#
  137.30 +# Contributor(s):
  137.31 +#
  137.32 +# The Original Software is NetBeans. The Initial Developer of the Original
  137.33 +# Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  137.34 +#
  137.35 +# If you wish your version of this file to be governed by only the CDDL
  137.36 +# or only the GPL Version 2, indicate your decision by adding
  137.37 +# "[Contributor] elects to include this software in this distribution
  137.38 +# under the [CDDL or GPL Version 2] license." If you do not indicate a
  137.39 +# single choice of license, a recipient has the option to distribute
  137.40 +# your version of this file under either the CDDL, the GPL Version 2 or
  137.41 +# to extend the choice of license to its licensees as provided above.
  137.42 +# However, if you add GPL Version 2 code and therefore, elected the GPL
  137.43 +# Version 2 license, then the option applies only if the new code is
  137.44 +# made subject to such option by the copyright holder.
  137.45 +#
  137.46 +
  137.47 +MSG_Completion_GET=The GET method means retrieve whatever information \
  137.48 + (in the form of an entity) is identified by the Request-URI. \
  137.49 + If the Request-URI refers to a data-producing process, \
  137.50 + it is the produced data which shall be returned as the entity in \
  137.51 + the response and not the source text of the process, \
  137.52 + unless that text happens to be the output of the process.
  137.53 +
  137.54 +MSG_Completion_HEAD=The HEAD method is identical to GET except that the server \
  137.55 + MUST NOT return a message-body in the response. The metainformation \
  137.56 + contained in the HTTP headers in response to a HEAD request SHOULD be \
  137.57 + identical to the information sent in response to a GET request. \
  137.58 + This method can be used for obtaining metainformation about the entity implied \
  137.59 + by the request without transferring the entity-body itself. \
  137.60 + This method is often used for testing hypertext links for validity, \
  137.61 + accessibility, and recent modification.
  137.62 +
  137.63 +MSG_Completion_POST=The POST method is used to request that the origin server \
  137.64 + accept the entity enclosed in the request as a new subordinate of the resource \
  137.65 + identified by the Request-URI in the Request-Line. POST is designed to allow \
  137.66 + a uniform method to cover annotation of existing resources,\ 
  137.67 + posting a message to a bulletin board, newsgroup, mailing list, or similar \
  137.68 + group of articles, providing a block of data, such as the result of submitting a \
  137.69 + form, to a data-handling process or extending a database through an append operation. \
  137.70 + The actual function performed by the POST method is determined by the server \
  137.71 + and is usually dependent on the Request-URI. The posted entity is subordinate \
  137.72 + to that URI in the same way that a file is subordinate to a directory containing it, \
  137.73 + a news article is subordinate to a newsgroup to which it is posted, \
  137.74 + or a record is subordinate to a database.
  137.75 +
  137.76 +MSG_Completion_PUT=The PUT method requests that the enclosed entity be stored \
  137.77 + under the supplied Request-URI. If the Request-URI refers to an already \
  137.78 + existing resource, the enclosed entity SHOULD be considered as a modified \
  137.79 + version of the one residing on the origin server. If the Request-URI does \
  137.80 + not point to an existing resource, and that URI is capable of being defined \
  137.81 + as a new resource by the requesting user agent, the origin server can \
  137.82 + create the resource with that URI. If a new resource is created, the origin \
  137.83 + server MUST inform the user agent via the 201 (Created) response. \
  137.84 + If an existing resource is modified, either the 200 (OK) or 204 (No Content) \
  137.85 + response codes SHOULD be sent to indicate successful completion of the request. \
  137.86 + If the resource could not be created or modified with the Request-URI, an \
  137.87 + appropriate error response SHOULD be given that reflects the nature of the problem. \
  137.88 + The recipient of the entity MUST NOT ignore any Content-* (e.g. Content-Range) \
  137.89 + headers that it does not understand or implement and MUST return \
  137.90 + a 501 (Not Implemented) response in such cases.
  137.91 +
  137.92 +MSG_Completion_DELETE=The DELETE method requests that the origin server delete \
  137.93 + the resource identified by the Request-URI. This method MAY be overridden \
  137.94 + by human intervention (or other means) on the origin server. The client \
  137.95 + cannot be guaranteed that the operation has been carried out, even if \
  137.96 + the status code returned from the origin server indicates that the action \
  137.97 + has been completed successfully. However, the server SHOULD NOT indicate \
  137.98 + success unless, at the time the response is given, it intends to delete \
  137.99 + the resource or move it to an inaccessible location.
 137.100 +
   138.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   138.2 +++ b/json/src/main/resources/org/netbeans/html/json/spi/package.html	Mon Dec 16 17:16:40 2013 +0100
   138.3 @@ -0,0 +1,59 @@
   138.4 +<!--
   138.5 +
   138.6 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   138.7 +
   138.8 +    Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   138.9 +
  138.10 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  138.11 +    Other names may be trademarks of their respective owners.
  138.12 +
  138.13 +    The contents of this file are subject to the terms of either the GNU
  138.14 +    General Public License Version 2 only ("GPL") or the Common
  138.15 +    Development and Distribution License("CDDL") (collectively, the
  138.16 +    "License"). You may not use this file except in compliance with the
  138.17 +    License. You can obtain a copy of the License at
  138.18 +    http://www.netbeans.org/cddl-gplv2.html
  138.19 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  138.20 +    specific language governing permissions and limitations under the
  138.21 +    License.  When distributing the software, include this License Header
  138.22 +    Notice in each file and include the License file at
  138.23 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  138.24 +    particular file as subject to the "Classpath" exception as provided
  138.25 +    by Oracle in the GPL Version 2 section of the License file that
  138.26 +    accompanied this code. If applicable, add the following below the
  138.27 +    License Header, with the fields enclosed by brackets [] replaced by
  138.28 +    your own identifying information:
  138.29 +    "Portions Copyrighted [year] [name of copyright owner]"
  138.30 +
  138.31 +    Contributor(s):
  138.32 +
  138.33 +    The Original Software is NetBeans. The Initial Developer of the Original
  138.34 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  138.35 +
  138.36 +    If you wish your version of this file to be governed by only the CDDL
  138.37 +    or only the GPL Version 2, indicate your decision by adding
  138.38 +    "[Contributor] elects to include this software in this distribution
  138.39 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
  138.40 +    single choice of license, a recipient has the option to distribute
  138.41 +    your version of this file under either the CDDL, the GPL Version 2 or
  138.42 +    to extend the choice of license to its licensees as provided above.
  138.43 +    However, if you add GPL Version 2 code and therefore, elected the GPL
  138.44 +    Version 2 license, then the option applies only if the new code is
  138.45 +    made subject to such option by the copyright holder.
  138.46 +
  138.47 +-->
  138.48 +<!DOCTYPE html>
  138.49 +<html>
  138.50 +    <head>
  138.51 +        <title></title>
  138.52 +        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  138.53 +    </head>
  138.54 +    <body>
  138.55 +        <div>Implement 
  138.56 +            <a href="Technology.html">Technology</a> and
  138.57 +            <a href="Transfer.html">Transfer</a> and use 
  138.58 +            <a href="ContextBuilder.html">ContextBuilder</a> to create an instance
  138.59 +            of <code>Context</code> representing your technology.
  138.60 +        </div>
  138.61 +    </body>
  138.62 +</html>
   139.1 --- a/json/src/test/java/net/java/html/json/BoardTest.java	Mon Dec 16 17:16:02 2013 +0100
   139.2 +++ b/json/src/test/java/net/java/html/json/BoardTest.java	Mon Dec 16 17:16:40 2013 +0100
   139.3 @@ -1,22 +1,44 @@
   139.4  /**
   139.5 - * HTML via Java(tm) Language Bindings
   139.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   139.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   139.8   *
   139.9 - * This program is free software: you can redistribute it and/or modify
  139.10 - * it under the terms of the GNU General Public License as published by
  139.11 - * the Free Software Foundation, version 2 of the License.
  139.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  139.13   *
  139.14 - * This program is distributed in the hope that it will be useful,
  139.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  139.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  139.17 - * GNU General Public License for more details. apidesign.org
  139.18 - * designates this particular file as subject to the
  139.19 - * "Classpath" exception as provided by apidesign.org
  139.20 - * in the License file that accompanied this code.
  139.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  139.22 + * Other names may be trademarks of their respective owners.
  139.23   *
  139.24 - * You should have received a copy of the GNU General Public License
  139.25 - * along with this program. Look for COPYING file in the top folder.
  139.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  139.27 + * The contents of this file are subject to the terms of either the GNU
  139.28 + * General Public License Version 2 only ("GPL") or the Common
  139.29 + * Development and Distribution License("CDDL") (collectively, the
  139.30 + * "License"). You may not use this file except in compliance with the
  139.31 + * License. You can obtain a copy of the License at
  139.32 + * http://www.netbeans.org/cddl-gplv2.html
  139.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  139.34 + * specific language governing permissions and limitations under the
  139.35 + * License.  When distributing the software, include this License Header
  139.36 + * Notice in each file and include the License file at
  139.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  139.38 + * particular file as subject to the "Classpath" exception as provided
  139.39 + * by Oracle in the GPL Version 2 section of the License file that
  139.40 + * accompanied this code. If applicable, add the following below the
  139.41 + * License Header, with the fields enclosed by brackets [] replaced by
  139.42 + * your own identifying information:
  139.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  139.44 + *
  139.45 + * Contributor(s):
  139.46 + *
  139.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  139.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  139.49 + *
  139.50 + * If you wish your version of this file to be governed by only the CDDL
  139.51 + * or only the GPL Version 2, indicate your decision by adding
  139.52 + * "[Contributor] elects to include this software in this distribution
  139.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  139.54 + * single choice of license, a recipient has the option to distribute
  139.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  139.56 + * to extend the choice of license to its licensees as provided above.
  139.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  139.58 + * Version 2 license, then the option applies only if the new code is
  139.59 + * made subject to such option by the copyright holder.
  139.60   */
  139.61  package net.java.html.json;
  139.62  
   140.1 --- a/json/src/test/java/net/java/html/json/Compile.java	Mon Dec 16 17:16:02 2013 +0100
   140.2 +++ b/json/src/test/java/net/java/html/json/Compile.java	Mon Dec 16 17:16:40 2013 +0100
   140.3 @@ -1,22 +1,44 @@
   140.4  /**
   140.5 - * HTML via Java(tm) Language Bindings
   140.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   140.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   140.8   *
   140.9 - * This program is free software: you can redistribute it and/or modify
  140.10 - * it under the terms of the GNU General Public License as published by
  140.11 - * the Free Software Foundation, version 2 of the License.
  140.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  140.13   *
  140.14 - * This program is distributed in the hope that it will be useful,
  140.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  140.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  140.17 - * GNU General Public License for more details. apidesign.org
  140.18 - * designates this particular file as subject to the
  140.19 - * "Classpath" exception as provided by apidesign.org
  140.20 - * in the License file that accompanied this code.
  140.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  140.22 + * Other names may be trademarks of their respective owners.
  140.23   *
  140.24 - * You should have received a copy of the GNU General Public License
  140.25 - * along with this program. Look for COPYING file in the top folder.
  140.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  140.27 + * The contents of this file are subject to the terms of either the GNU
  140.28 + * General Public License Version 2 only ("GPL") or the Common
  140.29 + * Development and Distribution License("CDDL") (collectively, the
  140.30 + * "License"). You may not use this file except in compliance with the
  140.31 + * License. You can obtain a copy of the License at
  140.32 + * http://www.netbeans.org/cddl-gplv2.html
  140.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  140.34 + * specific language governing permissions and limitations under the
  140.35 + * License.  When distributing the software, include this License Header
  140.36 + * Notice in each file and include the License file at
  140.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  140.38 + * particular file as subject to the "Classpath" exception as provided
  140.39 + * by Oracle in the GPL Version 2 section of the License file that
  140.40 + * accompanied this code. If applicable, add the following below the
  140.41 + * License Header, with the fields enclosed by brackets [] replaced by
  140.42 + * your own identifying information:
  140.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  140.44 + *
  140.45 + * Contributor(s):
  140.46 + *
  140.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  140.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  140.49 + *
  140.50 + * If you wish your version of this file to be governed by only the CDDL
  140.51 + * or only the GPL Version 2, indicate your decision by adding
  140.52 + * "[Contributor] elects to include this software in this distribution
  140.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  140.54 + * single choice of license, a recipient has the option to distribute
  140.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  140.56 + * to extend the choice of license to its licensees as provided above.
  140.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  140.58 + * Version 2 license, then the option applies only if the new code is
  140.59 + * made subject to such option by the copyright holder.
  140.60   */
  140.61  package net.java.html.json;
  140.62  
   141.1 --- a/json/src/test/java/net/java/html/json/MapModelTest.java	Mon Dec 16 17:16:02 2013 +0100
   141.2 +++ b/json/src/test/java/net/java/html/json/MapModelTest.java	Mon Dec 16 17:16:40 2013 +0100
   141.3 @@ -1,22 +1,44 @@
   141.4  /**
   141.5 - * HTML via Java(tm) Language Bindings
   141.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   141.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   141.8   *
   141.9 - * This program is free software: you can redistribute it and/or modify
  141.10 - * it under the terms of the GNU General Public License as published by
  141.11 - * the Free Software Foundation, version 2 of the License.
  141.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  141.13   *
  141.14 - * This program is distributed in the hope that it will be useful,
  141.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  141.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  141.17 - * GNU General Public License for more details. apidesign.org
  141.18 - * designates this particular file as subject to the
  141.19 - * "Classpath" exception as provided by apidesign.org
  141.20 - * in the License file that accompanied this code.
  141.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  141.22 + * Other names may be trademarks of their respective owners.
  141.23   *
  141.24 - * You should have received a copy of the GNU General Public License
  141.25 - * along with this program. Look for COPYING file in the top folder.
  141.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  141.27 + * The contents of this file are subject to the terms of either the GNU
  141.28 + * General Public License Version 2 only ("GPL") or the Common
  141.29 + * Development and Distribution License("CDDL") (collectively, the
  141.30 + * "License"). You may not use this file except in compliance with the
  141.31 + * License. You can obtain a copy of the License at
  141.32 + * http://www.netbeans.org/cddl-gplv2.html
  141.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  141.34 + * specific language governing permissions and limitations under the
  141.35 + * License.  When distributing the software, include this License Header
  141.36 + * Notice in each file and include the License file at
  141.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  141.38 + * particular file as subject to the "Classpath" exception as provided
  141.39 + * by Oracle in the GPL Version 2 section of the License file that
  141.40 + * accompanied this code. If applicable, add the following below the
  141.41 + * License Header, with the fields enclosed by brackets [] replaced by
  141.42 + * your own identifying information:
  141.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  141.44 + *
  141.45 + * Contributor(s):
  141.46 + *
  141.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  141.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  141.49 + *
  141.50 + * If you wish your version of this file to be governed by only the CDDL
  141.51 + * or only the GPL Version 2, indicate your decision by adding
  141.52 + * "[Contributor] elects to include this software in this distribution
  141.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  141.54 + * single choice of license, a recipient has the option to distribute
  141.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  141.56 + * to extend the choice of license to its licensees as provided above.
  141.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  141.58 + * Version 2 license, then the option applies only if the new code is
  141.59 + * made subject to such option by the copyright holder.
  141.60   */
  141.61  package net.java.html.json;
  141.62  
  141.63 @@ -27,7 +49,7 @@
  141.64  import java.util.HashMap;
  141.65  import java.util.Map;
  141.66  import org.apidesign.html.context.spi.Contexts;
  141.67 -import org.apidesign.html.json.impl.WrapperObject;
  141.68 +import org.netbeans.html.json.impl.WrapperObject;
  141.69  import org.apidesign.html.json.spi.FunctionBinding;
  141.70  import org.apidesign.html.json.spi.JSONCall;
  141.71  import org.apidesign.html.json.spi.PropertyBinding;
   142.1 --- a/json/src/test/java/net/java/html/json/ModelProcessorTest.java	Mon Dec 16 17:16:02 2013 +0100
   142.2 +++ b/json/src/test/java/net/java/html/json/ModelProcessorTest.java	Mon Dec 16 17:16:40 2013 +0100
   142.3 @@ -1,22 +1,44 @@
   142.4  /**
   142.5 - * HTML via Java(tm) Language Bindings
   142.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   142.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   142.8   *
   142.9 - * This program is free software: you can redistribute it and/or modify
  142.10 - * it under the terms of the GNU General Public License as published by
  142.11 - * the Free Software Foundation, version 2 of the License.
  142.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  142.13   *
  142.14 - * This program is distributed in the hope that it will be useful,
  142.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  142.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  142.17 - * GNU General Public License for more details. apidesign.org
  142.18 - * designates this particular file as subject to the
  142.19 - * "Classpath" exception as provided by apidesign.org
  142.20 - * in the License file that accompanied this code.
  142.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  142.22 + * Other names may be trademarks of their respective owners.
  142.23   *
  142.24 - * You should have received a copy of the GNU General Public License
  142.25 - * along with this program. Look for COPYING file in the top folder.
  142.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  142.27 + * The contents of this file are subject to the terms of either the GNU
  142.28 + * General Public License Version 2 only ("GPL") or the Common
  142.29 + * Development and Distribution License("CDDL") (collectively, the
  142.30 + * "License"). You may not use this file except in compliance with the
  142.31 + * License. You can obtain a copy of the License at
  142.32 + * http://www.netbeans.org/cddl-gplv2.html
  142.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  142.34 + * specific language governing permissions and limitations under the
  142.35 + * License.  When distributing the software, include this License Header
  142.36 + * Notice in each file and include the License file at
  142.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  142.38 + * particular file as subject to the "Classpath" exception as provided
  142.39 + * by Oracle in the GPL Version 2 section of the License file that
  142.40 + * accompanied this code. If applicable, add the following below the
  142.41 + * License Header, with the fields enclosed by brackets [] replaced by
  142.42 + * your own identifying information:
  142.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  142.44 + *
  142.45 + * Contributor(s):
  142.46 + *
  142.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  142.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  142.49 + *
  142.50 + * If you wish your version of this file to be governed by only the CDDL
  142.51 + * or only the GPL Version 2, indicate your decision by adding
  142.52 + * "[Contributor] elects to include this software in this distribution
  142.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  142.54 + * single choice of license, a recipient has the option to distribute
  142.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  142.56 + * to extend the choice of license to its licensees as provided above.
  142.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  142.58 + * Version 2 license, then the option applies only if the new code is
  142.59 + * made subject to such option by the copyright holder.
  142.60   */
  142.61  package net.java.html.json;
  142.62  
   143.1 --- a/json/src/test/java/net/java/html/json/ModelTest.java	Mon Dec 16 17:16:02 2013 +0100
   143.2 +++ b/json/src/test/java/net/java/html/json/ModelTest.java	Mon Dec 16 17:16:40 2013 +0100
   143.3 @@ -1,22 +1,44 @@
   143.4  /**
   143.5 - * HTML via Java(tm) Language Bindings
   143.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   143.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   143.8   *
   143.9 - * This program is free software: you can redistribute it and/or modify
  143.10 - * it under the terms of the GNU General Public License as published by
  143.11 - * the Free Software Foundation, version 2 of the License.
  143.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  143.13   *
  143.14 - * This program is distributed in the hope that it will be useful,
  143.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  143.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  143.17 - * GNU General Public License for more details. apidesign.org
  143.18 - * designates this particular file as subject to the
  143.19 - * "Classpath" exception as provided by apidesign.org
  143.20 - * in the License file that accompanied this code.
  143.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  143.22 + * Other names may be trademarks of their respective owners.
  143.23   *
  143.24 - * You should have received a copy of the GNU General Public License
  143.25 - * along with this program. Look for COPYING file in the top folder.
  143.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  143.27 + * The contents of this file are subject to the terms of either the GNU
  143.28 + * General Public License Version 2 only ("GPL") or the Common
  143.29 + * Development and Distribution License("CDDL") (collectively, the
  143.30 + * "License"). You may not use this file except in compliance with the
  143.31 + * License. You can obtain a copy of the License at
  143.32 + * http://www.netbeans.org/cddl-gplv2.html
  143.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  143.34 + * specific language governing permissions and limitations under the
  143.35 + * License.  When distributing the software, include this License Header
  143.36 + * Notice in each file and include the License file at
  143.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  143.38 + * particular file as subject to the "Classpath" exception as provided
  143.39 + * by Oracle in the GPL Version 2 section of the License file that
  143.40 + * accompanied this code. If applicable, add the following below the
  143.41 + * License Header, with the fields enclosed by brackets [] replaced by
  143.42 + * your own identifying information:
  143.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  143.44 + *
  143.45 + * Contributor(s):
  143.46 + *
  143.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  143.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  143.49 + *
  143.50 + * If you wish your version of this file to be governed by only the CDDL
  143.51 + * or only the GPL Version 2, indicate your decision by adding
  143.52 + * "[Contributor] elects to include this software in this distribution
  143.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  143.54 + * single choice of license, a recipient has the option to distribute
  143.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  143.56 + * to extend the choice of license to its licensees as provided above.
  143.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  143.58 + * Version 2 license, then the option applies only if the new code is
  143.59 + * made subject to such option by the copyright holder.
  143.60   */
  143.61  package net.java.html.json;
  143.62  
   144.1 --- a/json/src/test/java/net/java/html/json/ModelsTest.java	Mon Dec 16 17:16:02 2013 +0100
   144.2 +++ b/json/src/test/java/net/java/html/json/ModelsTest.java	Mon Dec 16 17:16:40 2013 +0100
   144.3 @@ -1,22 +1,44 @@
   144.4  /**
   144.5 - * HTML via Java(tm) Language Bindings
   144.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   144.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   144.8   *
   144.9 - * This program is free software: you can redistribute it and/or modify
  144.10 - * it under the terms of the GNU General Public License as published by
  144.11 - * the Free Software Foundation, version 2 of the License.
  144.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  144.13   *
  144.14 - * This program is distributed in the hope that it will be useful,
  144.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  144.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  144.17 - * GNU General Public License for more details. apidesign.org
  144.18 - * designates this particular file as subject to the
  144.19 - * "Classpath" exception as provided by apidesign.org
  144.20 - * in the License file that accompanied this code.
  144.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  144.22 + * Other names may be trademarks of their respective owners.
  144.23   *
  144.24 - * You should have received a copy of the GNU General Public License
  144.25 - * along with this program. Look for COPYING file in the top folder.
  144.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  144.27 + * The contents of this file are subject to the terms of either the GNU
  144.28 + * General Public License Version 2 only ("GPL") or the Common
  144.29 + * Development and Distribution License("CDDL") (collectively, the
  144.30 + * "License"). You may not use this file except in compliance with the
  144.31 + * License. You can obtain a copy of the License at
  144.32 + * http://www.netbeans.org/cddl-gplv2.html
  144.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  144.34 + * specific language governing permissions and limitations under the
  144.35 + * License.  When distributing the software, include this License Header
  144.36 + * Notice in each file and include the License file at
  144.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  144.38 + * particular file as subject to the "Classpath" exception as provided
  144.39 + * by Oracle in the GPL Version 2 section of the License file that
  144.40 + * accompanied this code. If applicable, add the following below the
  144.41 + * License Header, with the fields enclosed by brackets [] replaced by
  144.42 + * your own identifying information:
  144.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  144.44 + *
  144.45 + * Contributor(s):
  144.46 + *
  144.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  144.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  144.49 + *
  144.50 + * If you wish your version of this file to be governed by only the CDDL
  144.51 + * or only the GPL Version 2, indicate your decision by adding
  144.52 + * "[Contributor] elects to include this software in this distribution
  144.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  144.54 + * single choice of license, a recipient has the option to distribute
  144.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  144.56 + * to extend the choice of license to its licensees as provided above.
  144.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  144.58 + * Version 2 license, then the option applies only if the new code is
  144.59 + * made subject to such option by the copyright holder.
  144.60   */
  144.61  package net.java.html.json;
  144.62  
   145.1 --- a/json/src/test/java/net/java/html/json/OperationTest.java	Mon Dec 16 17:16:02 2013 +0100
   145.2 +++ b/json/src/test/java/net/java/html/json/OperationTest.java	Mon Dec 16 17:16:40 2013 +0100
   145.3 @@ -1,22 +1,44 @@
   145.4  /**
   145.5 - * HTML via Java(tm) Language Bindings
   145.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   145.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   145.8   *
   145.9 - * This program is free software: you can redistribute it and/or modify
  145.10 - * it under the terms of the GNU General Public License as published by
  145.11 - * the Free Software Foundation, version 2 of the License.
  145.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  145.13   *
  145.14 - * This program is distributed in the hope that it will be useful,
  145.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  145.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  145.17 - * GNU General Public License for more details. apidesign.org
  145.18 - * designates this particular file as subject to the
  145.19 - * "Classpath" exception as provided by apidesign.org
  145.20 - * in the License file that accompanied this code.
  145.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  145.22 + * Other names may be trademarks of their respective owners.
  145.23   *
  145.24 - * You should have received a copy of the GNU General Public License
  145.25 - * along with this program. Look for COPYING file in the top folder.
  145.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  145.27 + * The contents of this file are subject to the terms of either the GNU
  145.28 + * General Public License Version 2 only ("GPL") or the Common
  145.29 + * Development and Distribution License("CDDL") (collectively, the
  145.30 + * "License"). You may not use this file except in compliance with the
  145.31 + * License. You can obtain a copy of the License at
  145.32 + * http://www.netbeans.org/cddl-gplv2.html
  145.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  145.34 + * specific language governing permissions and limitations under the
  145.35 + * License.  When distributing the software, include this License Header
  145.36 + * Notice in each file and include the License file at
  145.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  145.38 + * particular file as subject to the "Classpath" exception as provided
  145.39 + * by Oracle in the GPL Version 2 section of the License file that
  145.40 + * accompanied this code. If applicable, add the following below the
  145.41 + * License Header, with the fields enclosed by brackets [] replaced by
  145.42 + * your own identifying information:
  145.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  145.44 + *
  145.45 + * Contributor(s):
  145.46 + *
  145.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  145.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  145.49 + *
  145.50 + * If you wish your version of this file to be governed by only the CDDL
  145.51 + * or only the GPL Version 2, indicate your decision by adding
  145.52 + * "[Contributor] elects to include this software in this distribution
  145.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  145.54 + * single choice of license, a recipient has the option to distribute
  145.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  145.56 + * to extend the choice of license to its licensees as provided above.
  145.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  145.58 + * Version 2 license, then the option applies only if the new code is
  145.59 + * made subject to such option by the copyright holder.
  145.60   */
  145.61  package net.java.html.json;
  145.62  
   146.1 --- a/json/src/test/java/net/java/html/json/PersonImpl.java	Mon Dec 16 17:16:02 2013 +0100
   146.2 +++ b/json/src/test/java/net/java/html/json/PersonImpl.java	Mon Dec 16 17:16:40 2013 +0100
   146.3 @@ -1,22 +1,44 @@
   146.4  /**
   146.5 - * HTML via Java(tm) Language Bindings
   146.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   146.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   146.8   *
   146.9 - * This program is free software: you can redistribute it and/or modify
  146.10 - * it under the terms of the GNU General Public License as published by
  146.11 - * the Free Software Foundation, version 2 of the License.
  146.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  146.13   *
  146.14 - * This program is distributed in the hope that it will be useful,
  146.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  146.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  146.17 - * GNU General Public License for more details. apidesign.org
  146.18 - * designates this particular file as subject to the
  146.19 - * "Classpath" exception as provided by apidesign.org
  146.20 - * in the License file that accompanied this code.
  146.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  146.22 + * Other names may be trademarks of their respective owners.
  146.23   *
  146.24 - * You should have received a copy of the GNU General Public License
  146.25 - * along with this program. Look for COPYING file in the top folder.
  146.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  146.27 + * The contents of this file are subject to the terms of either the GNU
  146.28 + * General Public License Version 2 only ("GPL") or the Common
  146.29 + * Development and Distribution License("CDDL") (collectively, the
  146.30 + * "License"). You may not use this file except in compliance with the
  146.31 + * License. You can obtain a copy of the License at
  146.32 + * http://www.netbeans.org/cddl-gplv2.html
  146.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  146.34 + * specific language governing permissions and limitations under the
  146.35 + * License.  When distributing the software, include this License Header
  146.36 + * Notice in each file and include the License file at
  146.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  146.38 + * particular file as subject to the "Classpath" exception as provided
  146.39 + * by Oracle in the GPL Version 2 section of the License file that
  146.40 + * accompanied this code. If applicable, add the following below the
  146.41 + * License Header, with the fields enclosed by brackets [] replaced by
  146.42 + * your own identifying information:
  146.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  146.44 + *
  146.45 + * Contributor(s):
  146.46 + *
  146.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  146.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  146.49 + *
  146.50 + * If you wish your version of this file to be governed by only the CDDL
  146.51 + * or only the GPL Version 2, indicate your decision by adding
  146.52 + * "[Contributor] elects to include this software in this distribution
  146.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  146.54 + * single choice of license, a recipient has the option to distribute
  146.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  146.56 + * to extend the choice of license to its licensees as provided above.
  146.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  146.58 + * Version 2 license, then the option applies only if the new code is
  146.59 + * made subject to such option by the copyright holder.
  146.60   */
  146.61  package net.java.html.json;
  146.62  
   147.1 --- a/json/src/test/java/net/java/html/json/PrimitiveArrayTest.java	Mon Dec 16 17:16:02 2013 +0100
   147.2 +++ b/json/src/test/java/net/java/html/json/PrimitiveArrayTest.java	Mon Dec 16 17:16:40 2013 +0100
   147.3 @@ -1,22 +1,44 @@
   147.4  /**
   147.5 - * HTML via Java(tm) Language Bindings
   147.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   147.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   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 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  147.13   *
  147.14 - * This program is distributed in the hope that it will be useful,
  147.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  147.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  147.17 - * GNU General Public License for more details. apidesign.org
  147.18 - * designates this particular file as subject to the
  147.19 - * "Classpath" exception as provided by apidesign.org
  147.20 - * in the License file that accompanied this code.
  147.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  147.22 + * Other names may be trademarks of their respective owners.
  147.23   *
  147.24 - * You should have received a copy of the GNU General Public License
  147.25 - * along with this program. Look for COPYING file in the top folder.
  147.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  147.27 + * The contents of this file are subject to the terms of either the GNU
  147.28 + * General Public License Version 2 only ("GPL") or the Common
  147.29 + * Development and Distribution License("CDDL") (collectively, the
  147.30 + * "License"). You may not use this file except in compliance with the
  147.31 + * License. You can obtain a copy of the License at
  147.32 + * http://www.netbeans.org/cddl-gplv2.html
  147.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  147.34 + * specific language governing permissions and limitations under the
  147.35 + * License.  When distributing the software, include this License Header
  147.36 + * Notice in each file and include the License file at
  147.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  147.38 + * particular file as subject to the "Classpath" exception as provided
  147.39 + * by Oracle in the GPL Version 2 section of the License file that
  147.40 + * accompanied this code. If applicable, add the following below the
  147.41 + * License Header, with the fields enclosed by brackets [] replaced by
  147.42 + * your own identifying information:
  147.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  147.44 + *
  147.45 + * Contributor(s):
  147.46 + *
  147.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  147.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  147.49 + *
  147.50 + * If you wish your version of this file to be governed by only the CDDL
  147.51 + * or only the GPL Version 2, indicate your decision by adding
  147.52 + * "[Contributor] elects to include this software in this distribution
  147.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  147.54 + * single choice of license, a recipient has the option to distribute
  147.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  147.56 + * to extend the choice of license to its licensees as provided above.
  147.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  147.58 + * Version 2 license, then the option applies only if the new code is
  147.59 + * made subject to such option by the copyright holder.
  147.60   */
  147.61  package net.java.html.json;
  147.62  
   148.1 --- a/json/src/test/java/net/java/html/json/Sex.java	Mon Dec 16 17:16:02 2013 +0100
   148.2 +++ b/json/src/test/java/net/java/html/json/Sex.java	Mon Dec 16 17:16:40 2013 +0100
   148.3 @@ -1,22 +1,44 @@
   148.4  /**
   148.5 - * HTML via Java(tm) Language Bindings
   148.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   148.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   148.8   *
   148.9 - * This program is free software: you can redistribute it and/or modify
  148.10 - * it under the terms of the GNU General Public License as published by
  148.11 - * the Free Software Foundation, version 2 of the License.
  148.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  148.13   *
  148.14 - * This program is distributed in the hope that it will be useful,
  148.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  148.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  148.17 - * GNU General Public License for more details. apidesign.org
  148.18 - * designates this particular file as subject to the
  148.19 - * "Classpath" exception as provided by apidesign.org
  148.20 - * in the License file that accompanied this code.
  148.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  148.22 + * Other names may be trademarks of their respective owners.
  148.23   *
  148.24 - * You should have received a copy of the GNU General Public License
  148.25 - * along with this program. Look for COPYING file in the top folder.
  148.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  148.27 + * The contents of this file are subject to the terms of either the GNU
  148.28 + * General Public License Version 2 only ("GPL") or the Common
  148.29 + * Development and Distribution License("CDDL") (collectively, the
  148.30 + * "License"). You may not use this file except in compliance with the
  148.31 + * License. You can obtain a copy of the License at
  148.32 + * http://www.netbeans.org/cddl-gplv2.html
  148.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  148.34 + * specific language governing permissions and limitations under the
  148.35 + * License.  When distributing the software, include this License Header
  148.36 + * Notice in each file and include the License file at
  148.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  148.38 + * particular file as subject to the "Classpath" exception as provided
  148.39 + * by Oracle in the GPL Version 2 section of the License file that
  148.40 + * accompanied this code. If applicable, add the following below the
  148.41 + * License Header, with the fields enclosed by brackets [] replaced by
  148.42 + * your own identifying information:
  148.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  148.44 + *
  148.45 + * Contributor(s):
  148.46 + *
  148.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  148.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  148.49 + *
  148.50 + * If you wish your version of this file to be governed by only the CDDL
  148.51 + * or only the GPL Version 2, indicate your decision by adding
  148.52 + * "[Contributor] elects to include this software in this distribution
  148.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  148.54 + * single choice of license, a recipient has the option to distribute
  148.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  148.56 + * to extend the choice of license to its licensees as provided above.
  148.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  148.58 + * Version 2 license, then the option applies only if the new code is
  148.59 + * made subject to such option by the copyright holder.
  148.60   */
  148.61  package net.java.html.json;
  148.62  
   149.1 --- a/json/src/test/java/net/java/html/json/TypesTest.java	Mon Dec 16 17:16:02 2013 +0100
   149.2 +++ b/json/src/test/java/net/java/html/json/TypesTest.java	Mon Dec 16 17:16:40 2013 +0100
   149.3 @@ -1,22 +1,44 @@
   149.4  /**
   149.5 - * HTML via Java(tm) Language Bindings
   149.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   149.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   149.8   *
   149.9 - * This program is free software: you can redistribute it and/or modify
  149.10 - * it under the terms of the GNU General Public License as published by
  149.11 - * the Free Software Foundation, version 2 of the License.
  149.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  149.13   *
  149.14 - * This program is distributed in the hope that it will be useful,
  149.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  149.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  149.17 - * GNU General Public License for more details. apidesign.org
  149.18 - * designates this particular file as subject to the
  149.19 - * "Classpath" exception as provided by apidesign.org
  149.20 - * in the License file that accompanied this code.
  149.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  149.22 + * Other names may be trademarks of their respective owners.
  149.23   *
  149.24 - * You should have received a copy of the GNU General Public License
  149.25 - * along with this program. Look for COPYING file in the top folder.
  149.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  149.27 + * The contents of this file are subject to the terms of either the GNU
  149.28 + * General Public License Version 2 only ("GPL") or the Common
  149.29 + * Development and Distribution License("CDDL") (collectively, the
  149.30 + * "License"). You may not use this file except in compliance with the
  149.31 + * License. You can obtain a copy of the License at
  149.32 + * http://www.netbeans.org/cddl-gplv2.html
  149.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  149.34 + * specific language governing permissions and limitations under the
  149.35 + * License.  When distributing the software, include this License Header
  149.36 + * Notice in each file and include the License file at
  149.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  149.38 + * particular file as subject to the "Classpath" exception as provided
  149.39 + * by Oracle in the GPL Version 2 section of the License file that
  149.40 + * accompanied this code. If applicable, add the following below the
  149.41 + * License Header, with the fields enclosed by brackets [] replaced by
  149.42 + * your own identifying information:
  149.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  149.44 + *
  149.45 + * Contributor(s):
  149.46 + *
  149.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  149.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  149.49 + *
  149.50 + * If you wish your version of this file to be governed by only the CDDL
  149.51 + * or only the GPL Version 2, indicate your decision by adding
  149.52 + * "[Contributor] elects to include this software in this distribution
  149.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  149.54 + * single choice of license, a recipient has the option to distribute
  149.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  149.56 + * to extend the choice of license to its licensees as provided above.
  149.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  149.58 + * Version 2 license, then the option applies only if the new code is
  149.59 + * made subject to such option by the copyright holder.
  149.60   */
  149.61  package net.java.html.json;
  149.62  
  149.63 @@ -24,7 +46,7 @@
  149.64  import java.util.Map;
  149.65  import net.java.html.json.MapModelTest.One;
  149.66  import org.apidesign.html.context.spi.Contexts;
  149.67 -import org.apidesign.html.json.impl.WrapperObject;
  149.68 +import org.netbeans.html.json.impl.WrapperObject;
  149.69  import org.apidesign.html.json.spi.Technology;
  149.70  import org.apidesign.html.json.spi.Transfer;
  149.71  import org.testng.annotations.BeforeMethod;
   150.1 --- a/json/src/test/java/net/java/html/json/WebSocketCallTest.java	Mon Dec 16 17:16:02 2013 +0100
   150.2 +++ b/json/src/test/java/net/java/html/json/WebSocketCallTest.java	Mon Dec 16 17:16:40 2013 +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 1997-2010 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/org/apidesign/html/json/impl/ConstructorTest.java	Mon Dec 16 17:16:02 2013 +0100
   151.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   151.3 @@ -1,58 +0,0 @@
   151.4 -/**
   151.5 - * HTML via Java(tm) Language Bindings
   151.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   151.7 - *
   151.8 - * This program is free software: you can redistribute it and/or modify
   151.9 - * it under the terms of the GNU General Public License as published by
  151.10 - * the Free Software Foundation, version 2 of the License.
  151.11 - *
  151.12 - * This program is distributed in the hope that it will be useful,
  151.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  151.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  151.15 - * GNU General Public License for more details. apidesign.org
  151.16 - * designates this particular file as subject to the
  151.17 - * "Classpath" exception as provided by apidesign.org
  151.18 - * in the License file that accompanied this code.
  151.19 - *
  151.20 - * You should have received a copy of the GNU General Public License
  151.21 - * along with this program. Look for COPYING file in the top folder.
  151.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  151.23 - */
  151.24 -package org.apidesign.html.json.impl;
  151.25 -
  151.26 -import net.java.html.json.Model;
  151.27 -import net.java.html.json.Property;
  151.28 -import static org.testng.Assert.assertNotNull;
  151.29 -import static org.testng.Assert.assertEquals;
  151.30 -import org.testng.annotations.Test;
  151.31 -
  151.32 -/**
  151.33 - *
  151.34 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  151.35 - */
  151.36 -@Model(className="Man", properties={
  151.37 -    @Property(name = "name", type = String.class),
  151.38 -    @Property(name = "other", type = Address.class, array = true),
  151.39 -    @Property(name = "primary", type = Address.class),
  151.40 -    @Property(name = "childrenNames", type = String.class, array = true)
  151.41 -})
  151.42 -public class ConstructorTest {
  151.43 -    @Model(className = "Address", properties = {
  151.44 -        @Property(name = "place", type = String.class)
  151.45 -    })
  151.46 -    static final class AddressModel {
  151.47 -    }
  151.48 -    
  151.49 -    @Test public void initializedByDefault() {
  151.50 -        Man m = new Man();
  151.51 -        assertNotNull(m.getPrimary(), "Single subobjects are initialized");
  151.52 -    }
  151.53 -    
  151.54 -    @Test public void hasRichConstructor() {
  151.55 -        Man m = new Man("Jarda", new Address("home"), new Address("work"), new Address("hotel"));
  151.56 -        assertEquals(m.getName(), "Jarda");
  151.57 -        assertNotNull(m.getPrimary(), "Primary address specified");
  151.58 -        assertNotNull(m.getPrimary().getPlace(), "home");
  151.59 -        assertEquals(m.getOther().size(), 2, "Two other addresses");
  151.60 -    }
  151.61 -}
   152.1 --- a/json/src/test/java/org/apidesign/html/json/impl/EmployeeImpl.java	Mon Dec 16 17:16:02 2013 +0100
   152.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   152.3 @@ -1,42 +0,0 @@
   152.4 -/**
   152.5 - * HTML via Java(tm) Language Bindings
   152.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   152.7 - *
   152.8 - * This program is free software: you can redistribute it and/or modify
   152.9 - * it under the terms of the GNU General Public License as published by
  152.10 - * the Free Software Foundation, version 2 of the License.
  152.11 - *
  152.12 - * This program is distributed in the hope that it will be useful,
  152.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  152.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  152.15 - * GNU General Public License for more details. apidesign.org
  152.16 - * designates this particular file as subject to the
  152.17 - * "Classpath" exception as provided by apidesign.org
  152.18 - * in the License file that accompanied this code.
  152.19 - *
  152.20 - * You should have received a copy of the GNU General Public License
  152.21 - * along with this program. Look for COPYING file in the top folder.
  152.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  152.23 - */
  152.24 -
  152.25 -package org.apidesign.html.json.impl;
  152.26 -
  152.27 -import net.java.html.json.Model;
  152.28 -import net.java.html.json.OnReceive;
  152.29 -import net.java.html.json.Person;
  152.30 -import net.java.html.json.Property;
  152.31 -
  152.32 -/**
  152.33 - *
  152.34 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  152.35 - */
  152.36 -@Model(className = "Employee", properties = {
  152.37 -    @Property(name = "person", type = Person.class),
  152.38 -    @Property(name = "employer", type = Employer.class)
  152.39 -})
  152.40 -public class EmployeeImpl {
  152.41 -    @OnReceive(url = "some/url")
  152.42 -    static void changePersonality(Employee e, Person p) {
  152.43 -        e.setPerson(p);
  152.44 -    }
  152.45 -}
   153.1 --- a/json/src/test/java/org/apidesign/html/json/impl/EmployerTest.java	Mon Dec 16 17:16:02 2013 +0100
   153.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   153.3 @@ -1,43 +0,0 @@
   153.4 -/**
   153.5 - * HTML via Java(tm) Language Bindings
   153.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   153.7 - *
   153.8 - * This program is free software: you can redistribute it and/or modify
   153.9 - * it under the terms of the GNU General Public License as published by
  153.10 - * the Free Software Foundation, version 2 of the License.
  153.11 - *
  153.12 - * This program is distributed in the hope that it will be useful,
  153.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  153.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  153.15 - * GNU General Public License for more details. apidesign.org
  153.16 - * designates this particular file as subject to the
  153.17 - * "Classpath" exception as provided by apidesign.org
  153.18 - * in the License file that accompanied this code.
  153.19 - *
  153.20 - * You should have received a copy of the GNU General Public License
  153.21 - * along with this program. Look for COPYING file in the top folder.
  153.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  153.23 - */
  153.24 -package org.apidesign.html.json.impl;
  153.25 -
  153.26 -import net.java.html.BrwsrCtx;
  153.27 -import net.java.html.json.Model;
  153.28 -import net.java.html.json.Models;
  153.29 -import net.java.html.json.Property;
  153.30 -import org.testng.Assert;
  153.31 -import org.testng.annotations.Test;
  153.32 -
  153.33 -/**
  153.34 - *
  153.35 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  153.36 - */
  153.37 -@Model(className = "Employer", properties = {
  153.38 -    @Property(name = "name", type = String.class)
  153.39 -})
  153.40 -public class EmployerTest {
  153.41 -    @Test public void preLoadsTheClass() {
  153.42 -        Employer em = Models.fromRaw(BrwsrCtx.EMPTY, Employer.class, this);
  153.43 -        Assert.assertNotNull(em, "Class loaded");
  153.44 -        em.applyBindings();
  153.45 -    }
  153.46 -}
   154.1 --- a/json/src/test/java/org/apidesign/html/json/impl/JSONListTest.java	Mon Dec 16 17:16:02 2013 +0100
   154.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   154.3 @@ -1,170 +0,0 @@
   154.4 -/**
   154.5 - * HTML via Java(tm) Language Bindings
   154.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   154.7 - *
   154.8 - * This program is free software: you can redistribute it and/or modify
   154.9 - * it under the terms of the GNU General Public License as published by
  154.10 - * the Free Software Foundation, version 2 of the License.
  154.11 - *
  154.12 - * This program is distributed in the hope that it will be useful,
  154.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  154.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  154.15 - * GNU General Public License for more details. apidesign.org
  154.16 - * designates this particular file as subject to the
  154.17 - * "Classpath" exception as provided by apidesign.org
  154.18 - * in the License file that accompanied this code.
  154.19 - *
  154.20 - * You should have received a copy of the GNU General Public License
  154.21 - * along with this program. Look for COPYING file in the top folder.
  154.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  154.23 - */
  154.24 -package org.apidesign.html.json.impl;
  154.25 -
  154.26 -import java.util.HashMap;
  154.27 -import java.util.Map;
  154.28 -import net.java.html.BrwsrCtx;
  154.29 -import net.java.html.json.Models;
  154.30 -import net.java.html.json.People;
  154.31 -import net.java.html.json.Person;
  154.32 -import net.java.html.json.Sex;
  154.33 -import org.apidesign.html.context.spi.Contexts;
  154.34 -import org.apidesign.html.json.spi.FunctionBinding;
  154.35 -import org.apidesign.html.json.spi.PropertyBinding;
  154.36 -import org.apidesign.html.json.spi.Technology;
  154.37 -import static org.testng.Assert.*;
  154.38 -import org.testng.annotations.BeforeMethod;
  154.39 -import org.testng.annotations.Test;
  154.40 -
  154.41 -/**
  154.42 - *
  154.43 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  154.44 - */
  154.45 -public class JSONListTest implements Technology<Object> {
  154.46 -    private boolean replaceArray;
  154.47 -    private final Map<String,PropertyBinding> bindings = new HashMap<String,PropertyBinding>();
  154.48 -    
  154.49 -    public JSONListTest() {
  154.50 -    }
  154.51 -    
  154.52 -    @BeforeMethod public void clear() {
  154.53 -        replaceArray = false;
  154.54 -    }
  154.55 -
  154.56 -    @Test public void testConvertorOnAnObject() {
  154.57 -        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
  154.58 -        
  154.59 -        Person p = Models.bind(new Person(), c);
  154.60 -        p.setFirstName("1");
  154.61 -        p.setLastName("2");
  154.62 -        p.setSex(Sex.MALE);
  154.63 -
  154.64 -        Object real = WrapperObject.find(p);
  154.65 -        assertEquals(this, real, "I am the right model");
  154.66 -    }
  154.67 -    
  154.68 -    @Test public void testConvertorOnAnArray() {
  154.69 -        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
  154.70 -        
  154.71 -        Person p = Models.bind(new Person(), c);
  154.72 -        p.setFirstName("1");
  154.73 -        p.setLastName("2");
  154.74 -        p.setSex(Sex.MALE);
  154.75 -        
  154.76 -        People people = Models.bind(new People(p), c).applyBindings();
  154.77 -        assertEquals(people.getInfo().toString(), "[{\"firstName\":\"1\",\"lastName\":\"2\",\"sex\":\"MALE\"}]", "Converted to real JSON");
  154.78 -        
  154.79 -        PropertyBinding pb = bindings.get("info");
  154.80 -        assertNotNull(pb, "Binding for info found");
  154.81 -        
  154.82 -        Object real = pb.getValue();
  154.83 -        assertTrue(real instanceof Object[], "It is an array: " + real);
  154.84 -        Object[] arr = (Object[])real;
  154.85 -        assertEquals(arr.length, 1, "Size is one");
  154.86 -        assertEquals(this, arr[0], "I am the right model");
  154.87 -    }
  154.88 -    
  154.89 -    @Test public void testNicknames() {
  154.90 -        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
  154.91 -        
  154.92 -        People people = Models.bind(new People(), c).applyBindings();
  154.93 -        people.getNicknames().add("One");
  154.94 -        people.getNicknames().add("Two");
  154.95 -        
  154.96 -        PropertyBinding pb = bindings.get("nicknames");
  154.97 -        assertNotNull(pb, "Binding for info found");
  154.98 -        
  154.99 -        Object real = pb.getValue();
 154.100 -        assertTrue(real instanceof Object[], "It is an array: " + real);
 154.101 -        Object[] arr = (Object[])real;
 154.102 -        assertEquals(arr.length, 2, "Length two");
 154.103 -        assertEquals(arr[0], "One", "Text should be in the model");
 154.104 -        assertEquals(arr[1], "Two", "2nd text in the model");
 154.105 -    }
 154.106 -    
 154.107 -    @Test public void testConvertorOnAnArrayWithWrapper() {
 154.108 -        this.replaceArray = true;
 154.109 -        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
 154.110 -        
 154.111 -        Person p = Models.bind(new Person(), c);
 154.112 -        p.setFirstName("1");
 154.113 -        p.setLastName("2");
 154.114 -        p.setSex(Sex.MALE);
 154.115 -        
 154.116 -        People people = Models.bind(new People(), c).applyBindings();
 154.117 -        people.getInfo().add(p);
 154.118 -        
 154.119 -        Object real = WrapperObject.find(people.getInfo());
 154.120 -        assertEquals(real, this, "I am the model of the array");
 154.121 -    }
 154.122 -
 154.123 -    @Test public void bindingsOnArray() {
 154.124 -        this.replaceArray = true;
 154.125 -        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
 154.126 -        
 154.127 -        People p = Models.bind(new People(), c).applyBindings();
 154.128 -        p.getAge().add(30);
 154.129 -        
 154.130 -        PropertyBinding pb = bindings.get("age");
 154.131 -        assertNotNull(pb, "There is a binding for age list");
 154.132 -        
 154.133 -        assertEquals(pb.getValue(), this, "I am the model of the array");
 154.134 -    }
 154.135 -
 154.136 -    @Override
 154.137 -    public Object wrapModel(Object model) {
 154.138 -        return this;
 154.139 -    }
 154.140 -
 154.141 -    @Override
 154.142 -    public void bind(PropertyBinding b, Object model, Object data) {
 154.143 -        bindings.put(b.getPropertyName(), b);
 154.144 -    }
 154.145 -
 154.146 -    @Override
 154.147 -    public void valueHasMutated(Object data, String propertyName) {
 154.148 -    }
 154.149 -
 154.150 -    @Override
 154.151 -    public void expose(FunctionBinding fb, Object model, Object d) {
 154.152 -    }
 154.153 -
 154.154 -    @Override
 154.155 -    public void applyBindings(Object data) {
 154.156 -    }
 154.157 -
 154.158 -    @Override
 154.159 -    public Object wrapArray(Object[] arr) {
 154.160 -        return replaceArray ? this : arr;
 154.161 -    }
 154.162 -
 154.163 -    @Override
 154.164 -    public <M> M toModel(Class<M> modelClass, Object data) {
 154.165 -        return modelClass.cast(data);
 154.166 -    }
 154.167 -
 154.168 -    @Override
 154.169 -    public void runSafe(Runnable r) {
 154.170 -        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
 154.171 -    }
 154.172 -
 154.173 -}
   155.1 --- a/json/src/test/java/org/apidesign/html/json/impl/JSONTest.java	Mon Dec 16 17:16:02 2013 +0100
   155.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   155.3 @@ -1,62 +0,0 @@
   155.4 -/**
   155.5 - * HTML via Java(tm) Language Bindings
   155.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   155.7 - *
   155.8 - * This program is free software: you can redistribute it and/or modify
   155.9 - * it under the terms of the GNU General Public License as published by
  155.10 - * the Free Software Foundation, version 2 of the License.
  155.11 - *
  155.12 - * This program is distributed in the hope that it will be useful,
  155.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  155.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  155.15 - * GNU General Public License for more details. apidesign.org
  155.16 - * designates this particular file as subject to the
  155.17 - * "Classpath" exception as provided by apidesign.org
  155.18 - * in the License file that accompanied this code.
  155.19 - *
  155.20 - * You should have received a copy of the GNU General Public License
  155.21 - * along with this program. Look for COPYING file in the top folder.
  155.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  155.23 - */
  155.24 -package org.apidesign.html.json.impl;
  155.25 -
  155.26 -import static org.testng.Assert.*;
  155.27 -import org.testng.annotations.Test;
  155.28 -
  155.29 -/**
  155.30 - *
  155.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  155.32 - */
  155.33 -public class JSONTest {
  155.34 -    
  155.35 -    public JSONTest() {
  155.36 -    }
  155.37 -
  155.38 -    @Test public void longToStringValue() {
  155.39 -        assertEquals(JSON.stringValue(Long.valueOf(1)), "1");
  155.40 -    }
  155.41 -    
  155.42 -    @Test public void booleanIsSortOfNumber() {
  155.43 -        assertEquals(JSON.numberValue(Boolean.TRUE), Integer.valueOf(1));
  155.44 -        assertEquals(JSON.numberValue(Boolean.FALSE), Integer.valueOf(0));
  155.45 -    }
  155.46 -    
  155.47 -    @Test public void numberToChar() {
  155.48 -        assertEquals(JSON.charValue(65), Character.valueOf('A'));
  155.49 -    }
  155.50 -    @Test public void booleanToChar() {
  155.51 -        assertEquals(JSON.charValue(false), Character.valueOf((char)0));
  155.52 -        assertEquals(JSON.charValue(true), Character.valueOf((char)1));
  155.53 -    }
  155.54 -    @Test public void stringToChar() {
  155.55 -        assertEquals(JSON.charValue("Ahoj"), Character.valueOf('A'));
  155.56 -    }
  155.57 -    @Test public void stringToBoolean() {
  155.58 -        assertEquals(JSON.boolValue("false"), Boolean.FALSE);
  155.59 -        assertEquals(JSON.boolValue("True"), Boolean.TRUE);
  155.60 -    }
  155.61 -    @Test public void numberToBoolean() {
  155.62 -        assertEquals(JSON.boolValue(0), Boolean.FALSE);
  155.63 -        assertEquals(JSON.boolValue(1), Boolean.TRUE);
  155.64 -    }
  155.65 -}
   156.1 --- a/json/src/test/java/org/apidesign/html/json/impl/NoPropertiesTest.java	Mon Dec 16 17:16:02 2013 +0100
   156.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   156.3 @@ -1,33 +0,0 @@
   156.4 -/**
   156.5 - * HTML via Java(tm) Language Bindings
   156.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   156.7 - *
   156.8 - * This program is free software: you can redistribute it and/or modify
   156.9 - * it under the terms of the GNU General Public License as published by
  156.10 - * the Free Software Foundation, version 2 of the License.
  156.11 - *
  156.12 - * This program is distributed in the hope that it will be useful,
  156.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  156.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  156.15 - * GNU General Public License for more details. apidesign.org
  156.16 - * designates this particular file as subject to the
  156.17 - * "Classpath" exception as provided by apidesign.org
  156.18 - * in the License file that accompanied this code.
  156.19 - *
  156.20 - * You should have received a copy of the GNU General Public License
  156.21 - * along with this program. Look for COPYING file in the top folder.
  156.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  156.23 - */
  156.24 -package org.apidesign.html.json.impl;
  156.25 -
  156.26 -import net.java.html.json.Model;
  156.27 -
  156.28 -/** Originally could not compile.
  156.29 - *
  156.30 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  156.31 - */
  156.32 -@Model(className="NoProperties", properties = {
  156.33 -})
  156.34 -public class NoPropertiesTest {
  156.35 -    
  156.36 -}
   157.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   157.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/ConstructorTest.java	Mon Dec 16 17:16:40 2013 +0100
   157.3 @@ -0,0 +1,80 @@
   157.4 +/**
   157.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   157.6 + *
   157.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   157.8 + *
   157.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  157.10 + * Other names may be trademarks of their respective owners.
  157.11 + *
  157.12 + * The contents of this file are subject to the terms of either the GNU
  157.13 + * General Public License Version 2 only ("GPL") or the Common
  157.14 + * Development and Distribution License("CDDL") (collectively, the
  157.15 + * "License"). You may not use this file except in compliance with the
  157.16 + * License. You can obtain a copy of the License at
  157.17 + * http://www.netbeans.org/cddl-gplv2.html
  157.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  157.19 + * specific language governing permissions and limitations under the
  157.20 + * License.  When distributing the software, include this License Header
  157.21 + * Notice in each file and include the License file at
  157.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  157.23 + * particular file as subject to the "Classpath" exception as provided
  157.24 + * by Oracle in the GPL Version 2 section of the License file that
  157.25 + * accompanied this code. If applicable, add the following below the
  157.26 + * License Header, with the fields enclosed by brackets [] replaced by
  157.27 + * your own identifying information:
  157.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  157.29 + *
  157.30 + * Contributor(s):
  157.31 + *
  157.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  157.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  157.34 + *
  157.35 + * If you wish your version of this file to be governed by only the CDDL
  157.36 + * or only the GPL Version 2, indicate your decision by adding
  157.37 + * "[Contributor] elects to include this software in this distribution
  157.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  157.39 + * single choice of license, a recipient has the option to distribute
  157.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  157.41 + * to extend the choice of license to its licensees as provided above.
  157.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  157.43 + * Version 2 license, then the option applies only if the new code is
  157.44 + * made subject to such option by the copyright holder.
  157.45 + */
  157.46 +package org.netbeans.html.json.impl;
  157.47 +
  157.48 +import net.java.html.json.Model;
  157.49 +import net.java.html.json.Property;
  157.50 +import static org.testng.Assert.assertNotNull;
  157.51 +import static org.testng.Assert.assertEquals;
  157.52 +import org.testng.annotations.Test;
  157.53 +
  157.54 +/**
  157.55 + *
  157.56 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  157.57 + */
  157.58 +@Model(className="Man", properties={
  157.59 +    @Property(name = "name", type = String.class),
  157.60 +    @Property(name = "other", type = Address.class, array = true),
  157.61 +    @Property(name = "primary", type = Address.class),
  157.62 +    @Property(name = "childrenNames", type = String.class, array = true)
  157.63 +})
  157.64 +public class ConstructorTest {
  157.65 +    @Model(className = "Address", properties = {
  157.66 +        @Property(name = "place", type = String.class)
  157.67 +    })
  157.68 +    static final class AddressModel {
  157.69 +    }
  157.70 +    
  157.71 +    @Test public void initializedByDefault() {
  157.72 +        Man m = new Man();
  157.73 +        assertNotNull(m.getPrimary(), "Single subobjects are initialized");
  157.74 +    }
  157.75 +    
  157.76 +    @Test public void hasRichConstructor() {
  157.77 +        Man m = new Man("Jarda", new Address("home"), new Address("work"), new Address("hotel"));
  157.78 +        assertEquals(m.getName(), "Jarda");
  157.79 +        assertNotNull(m.getPrimary(), "Primary address specified");
  157.80 +        assertNotNull(m.getPrimary().getPlace(), "home");
  157.81 +        assertEquals(m.getOther().size(), 2, "Two other addresses");
  157.82 +    }
  157.83 +}
   158.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   158.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/EmployeeImpl.java	Mon Dec 16 17:16:40 2013 +0100
   158.3 @@ -0,0 +1,63 @@
   158.4 +/**
   158.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   158.6 + *
   158.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   158.8 + *
   158.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  158.10 + * Other names may be trademarks of their respective owners.
  158.11 + *
  158.12 + * The contents of this file are subject to the terms of either the GNU
  158.13 + * General Public License Version 2 only ("GPL") or the Common
  158.14 + * Development and Distribution License("CDDL") (collectively, the
  158.15 + * "License"). You may not use this file except in compliance with the
  158.16 + * License. You can obtain a copy of the License at
  158.17 + * http://www.netbeans.org/cddl-gplv2.html
  158.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  158.19 + * specific language governing permissions and limitations under the
  158.20 + * License.  When distributing the software, include this License Header
  158.21 + * Notice in each file and include the License file at
  158.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  158.23 + * particular file as subject to the "Classpath" exception as provided
  158.24 + * by Oracle in the GPL Version 2 section of the License file that
  158.25 + * accompanied this code. If applicable, add the following below the
  158.26 + * License Header, with the fields enclosed by brackets [] replaced by
  158.27 + * your own identifying information:
  158.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  158.29 + *
  158.30 + * Contributor(s):
  158.31 + *
  158.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  158.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  158.34 + *
  158.35 + * If you wish your version of this file to be governed by only the CDDL
  158.36 + * or only the GPL Version 2, indicate your decision by adding
  158.37 + * "[Contributor] elects to include this software in this distribution
  158.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  158.39 + * single choice of license, a recipient has the option to distribute
  158.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  158.41 + * to extend the choice of license to its licensees as provided above.
  158.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  158.43 + * Version 2 license, then the option applies only if the new code is
  158.44 + * made subject to such option by the copyright holder.
  158.45 + */
  158.46 +package org.netbeans.html.json.impl;
  158.47 +
  158.48 +import net.java.html.json.Model;
  158.49 +import net.java.html.json.OnReceive;
  158.50 +import net.java.html.json.Person;
  158.51 +import net.java.html.json.Property;
  158.52 +
  158.53 +/**
  158.54 + *
  158.55 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  158.56 + */
  158.57 +@Model(className = "Employee", properties = {
  158.58 +    @Property(name = "person", type = Person.class),
  158.59 +    @Property(name = "employer", type = Employer.class)
  158.60 +})
  158.61 +public class EmployeeImpl {
  158.62 +    @OnReceive(url = "some/url")
  158.63 +    static void changePersonality(Employee e, Person p) {
  158.64 +        e.setPerson(p);
  158.65 +    }
  158.66 +}
   159.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   159.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/EmployerTest.java	Mon Dec 16 17:16:40 2013 +0100
   159.3 @@ -0,0 +1,65 @@
   159.4 +/**
   159.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   159.6 + *
   159.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   159.8 + *
   159.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  159.10 + * Other names may be trademarks of their respective owners.
  159.11 + *
  159.12 + * The contents of this file are subject to the terms of either the GNU
  159.13 + * General Public License Version 2 only ("GPL") or the Common
  159.14 + * Development and Distribution License("CDDL") (collectively, the
  159.15 + * "License"). You may not use this file except in compliance with the
  159.16 + * License. You can obtain a copy of the License at
  159.17 + * http://www.netbeans.org/cddl-gplv2.html
  159.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  159.19 + * specific language governing permissions and limitations under the
  159.20 + * License.  When distributing the software, include this License Header
  159.21 + * Notice in each file and include the License file at
  159.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  159.23 + * particular file as subject to the "Classpath" exception as provided
  159.24 + * by Oracle in the GPL Version 2 section of the License file that
  159.25 + * accompanied this code. If applicable, add the following below the
  159.26 + * License Header, with the fields enclosed by brackets [] replaced by
  159.27 + * your own identifying information:
  159.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  159.29 + *
  159.30 + * Contributor(s):
  159.31 + *
  159.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  159.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  159.34 + *
  159.35 + * If you wish your version of this file to be governed by only the CDDL
  159.36 + * or only the GPL Version 2, indicate your decision by adding
  159.37 + * "[Contributor] elects to include this software in this distribution
  159.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  159.39 + * single choice of license, a recipient has the option to distribute
  159.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  159.41 + * to extend the choice of license to its licensees as provided above.
  159.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  159.43 + * Version 2 license, then the option applies only if the new code is
  159.44 + * made subject to such option by the copyright holder.
  159.45 + */
  159.46 +package org.netbeans.html.json.impl;
  159.47 +
  159.48 +import net.java.html.BrwsrCtx;
  159.49 +import net.java.html.json.Model;
  159.50 +import net.java.html.json.Models;
  159.51 +import net.java.html.json.Property;
  159.52 +import org.testng.Assert;
  159.53 +import org.testng.annotations.Test;
  159.54 +
  159.55 +/**
  159.56 + *
  159.57 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  159.58 + */
  159.59 +@Model(className = "Employer", properties = {
  159.60 +    @Property(name = "name", type = String.class)
  159.61 +})
  159.62 +public class EmployerTest {
  159.63 +    @Test public void preLoadsTheClass() {
  159.64 +        Employer em = Models.fromRaw(BrwsrCtx.EMPTY, Employer.class, this);
  159.65 +        Assert.assertNotNull(em, "Class loaded");
  159.66 +        em.applyBindings();
  159.67 +    }
  159.68 +}
   160.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   160.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/JSONListTest.java	Mon Dec 16 17:16:40 2013 +0100
   160.3 @@ -0,0 +1,192 @@
   160.4 +/**
   160.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   160.6 + *
   160.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   160.8 + *
   160.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  160.10 + * Other names may be trademarks of their respective owners.
  160.11 + *
  160.12 + * The contents of this file are subject to the terms of either the GNU
  160.13 + * General Public License Version 2 only ("GPL") or the Common
  160.14 + * Development and Distribution License("CDDL") (collectively, the
  160.15 + * "License"). You may not use this file except in compliance with the
  160.16 + * License. You can obtain a copy of the License at
  160.17 + * http://www.netbeans.org/cddl-gplv2.html
  160.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  160.19 + * specific language governing permissions and limitations under the
  160.20 + * License.  When distributing the software, include this License Header
  160.21 + * Notice in each file and include the License file at
  160.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  160.23 + * particular file as subject to the "Classpath" exception as provided
  160.24 + * by Oracle in the GPL Version 2 section of the License file that
  160.25 + * accompanied this code. If applicable, add the following below the
  160.26 + * License Header, with the fields enclosed by brackets [] replaced by
  160.27 + * your own identifying information:
  160.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  160.29 + *
  160.30 + * Contributor(s):
  160.31 + *
  160.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  160.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  160.34 + *
  160.35 + * If you wish your version of this file to be governed by only the CDDL
  160.36 + * or only the GPL Version 2, indicate your decision by adding
  160.37 + * "[Contributor] elects to include this software in this distribution
  160.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  160.39 + * single choice of license, a recipient has the option to distribute
  160.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  160.41 + * to extend the choice of license to its licensees as provided above.
  160.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  160.43 + * Version 2 license, then the option applies only if the new code is
  160.44 + * made subject to such option by the copyright holder.
  160.45 + */
  160.46 +package org.netbeans.html.json.impl;
  160.47 +
  160.48 +import java.util.HashMap;
  160.49 +import java.util.Map;
  160.50 +import net.java.html.BrwsrCtx;
  160.51 +import net.java.html.json.Models;
  160.52 +import net.java.html.json.People;
  160.53 +import net.java.html.json.Person;
  160.54 +import net.java.html.json.Sex;
  160.55 +import org.apidesign.html.context.spi.Contexts;
  160.56 +import org.apidesign.html.json.spi.FunctionBinding;
  160.57 +import org.apidesign.html.json.spi.PropertyBinding;
  160.58 +import org.apidesign.html.json.spi.Technology;
  160.59 +import static org.testng.Assert.*;
  160.60 +import org.testng.annotations.BeforeMethod;
  160.61 +import org.testng.annotations.Test;
  160.62 +
  160.63 +/**
  160.64 + *
  160.65 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  160.66 + */
  160.67 +public class JSONListTest implements Technology<Object> {
  160.68 +    private boolean replaceArray;
  160.69 +    private final Map<String,PropertyBinding> bindings = new HashMap<String,PropertyBinding>();
  160.70 +    
  160.71 +    public JSONListTest() {
  160.72 +    }
  160.73 +    
  160.74 +    @BeforeMethod public void clear() {
  160.75 +        replaceArray = false;
  160.76 +    }
  160.77 +
  160.78 +    @Test public void testConvertorOnAnObject() {
  160.79 +        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
  160.80 +        
  160.81 +        Person p = Models.bind(new Person(), c);
  160.82 +        p.setFirstName("1");
  160.83 +        p.setLastName("2");
  160.84 +        p.setSex(Sex.MALE);
  160.85 +
  160.86 +        Object real = WrapperObject.find(p);
  160.87 +        assertEquals(this, real, "I am the right model");
  160.88 +    }
  160.89 +    
  160.90 +    @Test public void testConvertorOnAnArray() {
  160.91 +        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
  160.92 +        
  160.93 +        Person p = Models.bind(new Person(), c);
  160.94 +        p.setFirstName("1");
  160.95 +        p.setLastName("2");
  160.96 +        p.setSex(Sex.MALE);
  160.97 +        
  160.98 +        People people = Models.bind(new People(p), c).applyBindings();
  160.99 +        assertEquals(people.getInfo().toString(), "[{\"firstName\":\"1\",\"lastName\":\"2\",\"sex\":\"MALE\"}]", "Converted to real JSON");
 160.100 +        
 160.101 +        PropertyBinding pb = bindings.get("info");
 160.102 +        assertNotNull(pb, "Binding for info found");
 160.103 +        
 160.104 +        Object real = pb.getValue();
 160.105 +        assertTrue(real instanceof Object[], "It is an array: " + real);
 160.106 +        Object[] arr = (Object[])real;
 160.107 +        assertEquals(arr.length, 1, "Size is one");
 160.108 +        assertEquals(this, arr[0], "I am the right model");
 160.109 +    }
 160.110 +    
 160.111 +    @Test public void testNicknames() {
 160.112 +        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
 160.113 +        
 160.114 +        People people = Models.bind(new People(), c).applyBindings();
 160.115 +        people.getNicknames().add("One");
 160.116 +        people.getNicknames().add("Two");
 160.117 +        
 160.118 +        PropertyBinding pb = bindings.get("nicknames");
 160.119 +        assertNotNull(pb, "Binding for info found");
 160.120 +        
 160.121 +        Object real = pb.getValue();
 160.122 +        assertTrue(real instanceof Object[], "It is an array: " + real);
 160.123 +        Object[] arr = (Object[])real;
 160.124 +        assertEquals(arr.length, 2, "Length two");
 160.125 +        assertEquals(arr[0], "One", "Text should be in the model");
 160.126 +        assertEquals(arr[1], "Two", "2nd text in the model");
 160.127 +    }
 160.128 +    
 160.129 +    @Test public void testConvertorOnAnArrayWithWrapper() {
 160.130 +        this.replaceArray = true;
 160.131 +        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
 160.132 +        
 160.133 +        Person p = Models.bind(new Person(), c);
 160.134 +        p.setFirstName("1");
 160.135 +        p.setLastName("2");
 160.136 +        p.setSex(Sex.MALE);
 160.137 +        
 160.138 +        People people = Models.bind(new People(), c).applyBindings();
 160.139 +        people.getInfo().add(p);
 160.140 +        
 160.141 +        Object real = WrapperObject.find(people.getInfo());
 160.142 +        assertEquals(real, this, "I am the model of the array");
 160.143 +    }
 160.144 +
 160.145 +    @Test public void bindingsOnArray() {
 160.146 +        this.replaceArray = true;
 160.147 +        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
 160.148 +        
 160.149 +        People p = Models.bind(new People(), c).applyBindings();
 160.150 +        p.getAge().add(30);
 160.151 +        
 160.152 +        PropertyBinding pb = bindings.get("age");
 160.153 +        assertNotNull(pb, "There is a binding for age list");
 160.154 +        
 160.155 +        assertEquals(pb.getValue(), this, "I am the model of the array");
 160.156 +    }
 160.157 +
 160.158 +    @Override
 160.159 +    public Object wrapModel(Object model) {
 160.160 +        return this;
 160.161 +    }
 160.162 +
 160.163 +    @Override
 160.164 +    public void bind(PropertyBinding b, Object model, Object data) {
 160.165 +        bindings.put(b.getPropertyName(), b);
 160.166 +    }
 160.167 +
 160.168 +    @Override
 160.169 +    public void valueHasMutated(Object data, String propertyName) {
 160.170 +    }
 160.171 +
 160.172 +    @Override
 160.173 +    public void expose(FunctionBinding fb, Object model, Object d) {
 160.174 +    }
 160.175 +
 160.176 +    @Override
 160.177 +    public void applyBindings(Object data) {
 160.178 +    }
 160.179 +
 160.180 +    @Override
 160.181 +    public Object wrapArray(Object[] arr) {
 160.182 +        return replaceArray ? this : arr;
 160.183 +    }
 160.184 +
 160.185 +    @Override
 160.186 +    public <M> M toModel(Class<M> modelClass, Object data) {
 160.187 +        return modelClass.cast(data);
 160.188 +    }
 160.189 +
 160.190 +    @Override
 160.191 +    public void runSafe(Runnable r) {
 160.192 +        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
 160.193 +    }
 160.194 +
 160.195 +}
   161.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   161.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/JSONTest.java	Mon Dec 16 17:16:40 2013 +0100
   161.3 @@ -0,0 +1,85 @@
   161.4 +/**
   161.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   161.6 + *
   161.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   161.8 + *
   161.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  161.10 + * Other names may be trademarks of their respective owners.
  161.11 + *
  161.12 + * The contents of this file are subject to the terms of either the GNU
  161.13 + * General Public License Version 2 only ("GPL") or the Common
  161.14 + * Development and Distribution License("CDDL") (collectively, the
  161.15 + * "License"). You may not use this file except in compliance with the
  161.16 + * License. You can obtain a copy of the License at
  161.17 + * http://www.netbeans.org/cddl-gplv2.html
  161.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  161.19 + * specific language governing permissions and limitations under the
  161.20 + * License.  When distributing the software, include this License Header
  161.21 + * Notice in each file and include the License file at
  161.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  161.23 + * particular file as subject to the "Classpath" exception as provided
  161.24 + * by Oracle in the GPL Version 2 section of the License file that
  161.25 + * accompanied this code. If applicable, add the following below the
  161.26 + * License Header, with the fields enclosed by brackets [] replaced by
  161.27 + * your own identifying information:
  161.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  161.29 + *
  161.30 + * Contributor(s):
  161.31 + *
  161.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  161.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  161.34 + *
  161.35 + * If you wish your version of this file to be governed by only the CDDL
  161.36 + * or only the GPL Version 2, indicate your decision by adding
  161.37 + * "[Contributor] elects to include this software in this distribution
  161.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  161.39 + * single choice of license, a recipient has the option to distribute
  161.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  161.41 + * to extend the choice of license to its licensees as provided above.
  161.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  161.43 + * Version 2 license, then the option applies only if the new code is
  161.44 + * made subject to such option by the copyright holder.
  161.45 + */
  161.46 +package org.netbeans.html.json.impl;
  161.47 +
  161.48 +import org.netbeans.html.json.impl.JSON;
  161.49 +import static org.testng.Assert.*;
  161.50 +import org.testng.annotations.Test;
  161.51 +
  161.52 +/**
  161.53 + *
  161.54 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  161.55 + */
  161.56 +public class JSONTest {
  161.57 +    
  161.58 +    public JSONTest() {
  161.59 +    }
  161.60 +
  161.61 +    @Test public void longToStringValue() {
  161.62 +        assertEquals(JSON.stringValue(Long.valueOf(1)), "1");
  161.63 +    }
  161.64 +    
  161.65 +    @Test public void booleanIsSortOfNumber() {
  161.66 +        assertEquals(JSON.numberValue(Boolean.TRUE), Integer.valueOf(1));
  161.67 +        assertEquals(JSON.numberValue(Boolean.FALSE), Integer.valueOf(0));
  161.68 +    }
  161.69 +    
  161.70 +    @Test public void numberToChar() {
  161.71 +        assertEquals(JSON.charValue(65), Character.valueOf('A'));
  161.72 +    }
  161.73 +    @Test public void booleanToChar() {
  161.74 +        assertEquals(JSON.charValue(false), Character.valueOf((char)0));
  161.75 +        assertEquals(JSON.charValue(true), Character.valueOf((char)1));
  161.76 +    }
  161.77 +    @Test public void stringToChar() {
  161.78 +        assertEquals(JSON.charValue("Ahoj"), Character.valueOf('A'));
  161.79 +    }
  161.80 +    @Test public void stringToBoolean() {
  161.81 +        assertEquals(JSON.boolValue("false"), Boolean.FALSE);
  161.82 +        assertEquals(JSON.boolValue("True"), Boolean.TRUE);
  161.83 +    }
  161.84 +    @Test public void numberToBoolean() {
  161.85 +        assertEquals(JSON.boolValue(0), Boolean.FALSE);
  161.86 +        assertEquals(JSON.boolValue(1), Boolean.TRUE);
  161.87 +    }
  161.88 +}
   162.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   162.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/NoPropertiesTest.java	Mon Dec 16 17:16:40 2013 +0100
   162.3 @@ -0,0 +1,55 @@
   162.4 +/**
   162.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   162.6 + *
   162.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   162.8 + *
   162.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  162.10 + * Other names may be trademarks of their respective owners.
  162.11 + *
  162.12 + * The contents of this file are subject to the terms of either the GNU
  162.13 + * General Public License Version 2 only ("GPL") or the Common
  162.14 + * Development and Distribution License("CDDL") (collectively, the
  162.15 + * "License"). You may not use this file except in compliance with the
  162.16 + * License. You can obtain a copy of the License at
  162.17 + * http://www.netbeans.org/cddl-gplv2.html
  162.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  162.19 + * specific language governing permissions and limitations under the
  162.20 + * License.  When distributing the software, include this License Header
  162.21 + * Notice in each file and include the License file at
  162.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  162.23 + * particular file as subject to the "Classpath" exception as provided
  162.24 + * by Oracle in the GPL Version 2 section of the License file that
  162.25 + * accompanied this code. If applicable, add the following below the
  162.26 + * License Header, with the fields enclosed by brackets [] replaced by
  162.27 + * your own identifying information:
  162.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  162.29 + *
  162.30 + * Contributor(s):
  162.31 + *
  162.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  162.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  162.34 + *
  162.35 + * If you wish your version of this file to be governed by only the CDDL
  162.36 + * or only the GPL Version 2, indicate your decision by adding
  162.37 + * "[Contributor] elects to include this software in this distribution
  162.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  162.39 + * single choice of license, a recipient has the option to distribute
  162.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  162.41 + * to extend the choice of license to its licensees as provided above.
  162.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  162.43 + * Version 2 license, then the option applies only if the new code is
  162.44 + * made subject to such option by the copyright holder.
  162.45 + */
  162.46 +package org.netbeans.html.json.impl;
  162.47 +
  162.48 +import net.java.html.json.Model;
  162.49 +
  162.50 +/** Originally could not compile.
  162.51 + *
  162.52 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  162.53 + */
  162.54 +@Model(className="NoProperties", properties = {
  162.55 +})
  162.56 +public class NoPropertiesTest {
  162.57 +    
  162.58 +}
   163.1 --- a/ko-archetype-test/pom.xml	Mon Dec 16 17:16:02 2013 +0100
   163.2 +++ b/ko-archetype-test/pom.xml	Mon Dec 16 17:16:40 2013 +0100
   163.3 @@ -2,11 +2,11 @@
   163.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">
   163.5      <modelVersion>4.0.0</modelVersion>
   163.6      <parent>
   163.7 -        <groupId>org.apidesign</groupId>
   163.8 -        <artifactId>html</artifactId>
   163.9 +        <groupId>org.netbeans.html</groupId>
  163.10 +        <artifactId>pom</artifactId>
  163.11          <version>0.7-SNAPSHOT</version>
  163.12      </parent>
  163.13 -    <groupId>org.apidesign.html</groupId>
  163.14 +    <groupId>org.netbeans.html</groupId>
  163.15      <artifactId>ko-archetype-test</artifactId>
  163.16      <version>0.7-SNAPSHOT</version>
  163.17      <name>Knockout 4 Java Archetype Test</name>
   164.1 --- a/ko-archetype-test/src/test/java/org/apidesign/html/archetype/test/ArchetypeVersionTest.java	Mon Dec 16 17:16:02 2013 +0100
   164.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   164.3 @@ -1,106 +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.archetype.test;
  164.25 -
  164.26 -import java.io.IOException;
  164.27 -import java.net.URL;
  164.28 -import javax.xml.XMLConstants;
  164.29 -import javax.xml.parsers.DocumentBuilderFactory;
  164.30 -import javax.xml.parsers.ParserConfigurationException;
  164.31 -import javax.xml.xpath.XPathConstants;
  164.32 -import javax.xml.xpath.XPathExpression;
  164.33 -import javax.xml.xpath.XPathExpressionException;
  164.34 -import javax.xml.xpath.XPathFactory;
  164.35 -import javax.xml.xpath.XPathFactoryConfigurationException;
  164.36 -import org.testng.annotations.Test;
  164.37 -import static org.testng.Assert.*;
  164.38 -import org.testng.annotations.BeforeClass;
  164.39 -import org.w3c.dom.Document;
  164.40 -import org.w3c.dom.NodeList;
  164.41 -import org.xml.sax.SAXException;
  164.42 -
  164.43 -/**
  164.44 - *
  164.45 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  164.46 - */
  164.47 -public class ArchetypeVersionTest {
  164.48 -    private String version;
  164.49 -    
  164.50 -    public ArchetypeVersionTest() {
  164.51 -    }
  164.52 -    
  164.53 -    @BeforeClass public void readCurrentVersion() throws Exception {
  164.54 -        version = findCurrentVersion();
  164.55 -        assertFalse(version.isEmpty(), "There should be some version string");
  164.56 -    }
  164.57 -    
  164.58 -
  164.59 -    @Test public void testComparePomDepsVersions() throws Exception {
  164.60 -        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
  164.61 -        URL r = l.getResource("archetype-resources/pom.xml");
  164.62 -        assertNotNull(r, "Archetype pom found");
  164.63 -        
  164.64 -        final XPathFactory fact = XPathFactory.newInstance();
  164.65 -        XPathExpression xp2 = fact.newXPath().compile(
  164.66 -            "//properties/net.java.html.version/text()"
  164.67 -        );
  164.68 -        
  164.69 -        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
  164.70 -        String arch = (String) xp2.evaluate(dom, XPathConstants.STRING);
  164.71 -
  164.72 -        assertEquals(arch, version, "net.java.html.json dependency needs to be on latest version");
  164.73 -    }
  164.74 -    
  164.75 -    @Test public void testNbActions() throws Exception {
  164.76 -        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
  164.77 -        URL r = l.getResource("archetype-resources/nbactions.xml");
  164.78 -        assertNotNull(r, "Archetype nb file found");
  164.79 -        
  164.80 -        final XPathFactory fact = XPathFactory.newInstance();
  164.81 -        XPathExpression xp2 = fact.newXPath().compile(
  164.82 -            "//goal/text()"
  164.83 -        );
  164.84 -        
  164.85 -        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
  164.86 -        NodeList goals = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
  164.87 -        
  164.88 -        for (int i = 0; i < goals.getLength(); i++) {
  164.89 -            String s = goals.item(i).getTextContent();
  164.90 -            if (s.contains("apidesign")) {
  164.91 -                assertFalse(s.matches(".*apidesign.*[0-9].*"), "No numbers: " + s);
  164.92 -            }
  164.93 -        }
  164.94 -    }
  164.95 -
  164.96 -    static String findCurrentVersion() throws XPathExpressionException, IOException, ParserConfigurationException, SAXException, XPathFactoryConfigurationException {
  164.97 -        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
  164.98 -        URL u = l.getResource("META-INF/maven/org.apidesign.html/knockout4j-archetype/pom.xml");
  164.99 -        assertNotNull(u, "Own pom found: " + System.getProperty("java.class.path"));
 164.100 -
 164.101 -        final XPathFactory fact = XPathFactory.newInstance();
 164.102 -        fact.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
 164.103 -
 164.104 -        XPathExpression xp = fact.newXPath().compile("project/version/text()");
 164.105 -        
 164.106 -        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(u.openStream());
 164.107 -        return xp.evaluate(dom);
 164.108 -    }
 164.109 -}
   165.1 --- a/ko-archetype-test/src/test/java/org/apidesign/html/archetype/test/VerifyArchetypeTest.java	Mon Dec 16 17:16:02 2013 +0100
   165.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   165.3 @@ -1,77 +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.archetype.test;
  165.25 -
  165.26 -import java.io.File;
  165.27 -import java.util.Properties;
  165.28 -import org.apache.maven.it.Verifier;
  165.29 -import org.testng.annotations.Test;
  165.30 -import static org.testng.Assert.*;
  165.31 -
  165.32 -/**
  165.33 - *
  165.34 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  165.35 - */
  165.36 -public class VerifyArchetypeTest {
  165.37 -    @Test public void projectCompiles() throws Exception {
  165.38 -        final File dir = new File("target/tests/fxcompile/").getAbsoluteFile();
  165.39 -        generateFromArchetype(dir);
  165.40 -        
  165.41 -        File created = new File(dir, "o-a-test");
  165.42 -        assertTrue(created.isDirectory(), "Project created");
  165.43 -        assertTrue(new File(created, "pom.xml").isFile(), "Pom file is in there");
  165.44 -        
  165.45 -        Verifier v = new Verifier(created.getAbsolutePath());
  165.46 -        v.executeGoal("verify");
  165.47 -        
  165.48 -        v.verifyErrorFreeLog();
  165.49 -        
  165.50 -        for (String l : v.loadFile(v.getBasedir(), v.getLogFileName(), false)) {
  165.51 -            if (l.contains("j2js")) {
  165.52 -                fail("No pre-compilaton:\n" + l);
  165.53 -            }
  165.54 -        }
  165.55 -        
  165.56 -        v.verifyTextInLog("fxcompile/o-a-test/target/o-a-test-1.0-SNAPSHOT-html.java.net.zip");
  165.57 -    }
  165.58 -    
  165.59 -    private Verifier generateFromArchetype(final File dir, String... params) throws Exception {
  165.60 -        Verifier v = new Verifier(dir.getAbsolutePath());
  165.61 -        v.setAutoclean(false);
  165.62 -        v.setLogFileName("generate.log");
  165.63 -        v.deleteDirectory("");
  165.64 -        dir.mkdirs();
  165.65 -        Properties sysProp = v.getSystemProperties();
  165.66 -        sysProp.put("groupId", "org.apidesign.test");
  165.67 -        sysProp.put("artifactId", "o-a-test");
  165.68 -        sysProp.put("package", "org.apidesign.test.oat");
  165.69 -        sysProp.put("archetypeGroupId", "org.apidesign.html");
  165.70 -        sysProp.put("archetypeArtifactId", "knockout4j-archetype");
  165.71 -        sysProp.put("archetypeVersion", ArchetypeVersionTest.findCurrentVersion());
  165.72 -        
  165.73 -        for (String p : params) {
  165.74 -            v.addCliOption(p);
  165.75 -        }
  165.76 -        v.executeGoal("archetype:generate");
  165.77 -        v.verifyErrorFreeLog();
  165.78 -        return v;
  165.79 -    }
  165.80 -}
   166.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   166.2 +++ b/ko-archetype-test/src/test/java/org/netbeans/html/archetype/test/ArchetypeVersionTest.java	Mon Dec 16 17:16:40 2013 +0100
   166.3 @@ -0,0 +1,128 @@
   166.4 +/**
   166.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   166.6 + *
   166.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   166.8 + *
   166.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  166.10 + * Other names may be trademarks of their respective owners.
  166.11 + *
  166.12 + * The contents of this file are subject to the terms of either the GNU
  166.13 + * General Public License Version 2 only ("GPL") or the Common
  166.14 + * Development and Distribution License("CDDL") (collectively, the
  166.15 + * "License"). You may not use this file except in compliance with the
  166.16 + * License. You can obtain a copy of the License at
  166.17 + * http://www.netbeans.org/cddl-gplv2.html
  166.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  166.19 + * specific language governing permissions and limitations under the
  166.20 + * License.  When distributing the software, include this License Header
  166.21 + * Notice in each file and include the License file at
  166.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  166.23 + * particular file as subject to the "Classpath" exception as provided
  166.24 + * by Oracle in the GPL Version 2 section of the License file that
  166.25 + * accompanied this code. If applicable, add the following below the
  166.26 + * License Header, with the fields enclosed by brackets [] replaced by
  166.27 + * your own identifying information:
  166.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  166.29 + *
  166.30 + * Contributor(s):
  166.31 + *
  166.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  166.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  166.34 + *
  166.35 + * If you wish your version of this file to be governed by only the CDDL
  166.36 + * or only the GPL Version 2, indicate your decision by adding
  166.37 + * "[Contributor] elects to include this software in this distribution
  166.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  166.39 + * single choice of license, a recipient has the option to distribute
  166.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  166.41 + * to extend the choice of license to its licensees as provided above.
  166.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  166.43 + * Version 2 license, then the option applies only if the new code is
  166.44 + * made subject to such option by the copyright holder.
  166.45 + */
  166.46 +package org.netbeans.html.archetype.test;
  166.47 +
  166.48 +import java.io.IOException;
  166.49 +import java.net.URL;
  166.50 +import javax.xml.XMLConstants;
  166.51 +import javax.xml.parsers.DocumentBuilderFactory;
  166.52 +import javax.xml.parsers.ParserConfigurationException;
  166.53 +import javax.xml.xpath.XPathConstants;
  166.54 +import javax.xml.xpath.XPathExpression;
  166.55 +import javax.xml.xpath.XPathExpressionException;
  166.56 +import javax.xml.xpath.XPathFactory;
  166.57 +import javax.xml.xpath.XPathFactoryConfigurationException;
  166.58 +import org.testng.annotations.Test;
  166.59 +import static org.testng.Assert.*;
  166.60 +import org.testng.annotations.BeforeClass;
  166.61 +import org.w3c.dom.Document;
  166.62 +import org.w3c.dom.NodeList;
  166.63 +import org.xml.sax.SAXException;
  166.64 +
  166.65 +/**
  166.66 + *
  166.67 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  166.68 + */
  166.69 +public class ArchetypeVersionTest {
  166.70 +    private String version;
  166.71 +    
  166.72 +    public ArchetypeVersionTest() {
  166.73 +    }
  166.74 +    
  166.75 +    @BeforeClass public void readCurrentVersion() throws Exception {
  166.76 +        version = findCurrentVersion();
  166.77 +        assertFalse(version.isEmpty(), "There should be some version string");
  166.78 +    }
  166.79 +    
  166.80 +
  166.81 +    @Test public void testComparePomDepsVersions() throws Exception {
  166.82 +        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
  166.83 +        URL r = l.getResource("archetype-resources/pom.xml");
  166.84 +        assertNotNull(r, "Archetype pom found");
  166.85 +        
  166.86 +        final XPathFactory fact = XPathFactory.newInstance();
  166.87 +        XPathExpression xp2 = fact.newXPath().compile(
  166.88 +            "//properties/net.java.html.version/text()"
  166.89 +        );
  166.90 +        
  166.91 +        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
  166.92 +        String arch = (String) xp2.evaluate(dom, XPathConstants.STRING);
  166.93 +
  166.94 +        assertEquals(arch, version, "net.java.html.json dependency needs to be on latest version");
  166.95 +    }
  166.96 +    
  166.97 +    @Test public void testNbActions() throws Exception {
  166.98 +        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
  166.99 +        URL r = l.getResource("archetype-resources/nbactions.xml");
 166.100 +        assertNotNull(r, "Archetype nb file found");
 166.101 +        
 166.102 +        final XPathFactory fact = XPathFactory.newInstance();
 166.103 +        XPathExpression xp2 = fact.newXPath().compile(
 166.104 +            "//goal/text()"
 166.105 +        );
 166.106 +        
 166.107 +        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
 166.108 +        NodeList goals = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
 166.109 +        
 166.110 +        for (int i = 0; i < goals.getLength(); i++) {
 166.111 +            String s = goals.item(i).getTextContent();
 166.112 +            if (s.contains("apidesign")) {
 166.113 +                assertFalse(s.matches(".*apidesign.*[0-9].*"), "No numbers: " + s);
 166.114 +            }
 166.115 +        }
 166.116 +    }
 166.117 +
 166.118 +    static String findCurrentVersion() throws XPathExpressionException, IOException, ParserConfigurationException, SAXException, XPathFactoryConfigurationException {
 166.119 +        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
 166.120 +        URL u = l.getResource("META-INF/maven/org.netbeans.html/knockout4j-archetype/pom.xml");
 166.121 +        assertNotNull(u, "Own pom found: " + System.getProperty("java.class.path"));
 166.122 +
 166.123 +        final XPathFactory fact = XPathFactory.newInstance();
 166.124 +        fact.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
 166.125 +
 166.126 +        XPathExpression xp = fact.newXPath().compile("project/version/text()");
 166.127 +        
 166.128 +        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(u.openStream());
 166.129 +        return xp.evaluate(dom);
 166.130 +    }
 166.131 +}
   167.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   167.2 +++ b/ko-archetype-test/src/test/java/org/netbeans/html/archetype/test/VerifyArchetypeTest.java	Mon Dec 16 17:16:40 2013 +0100
   167.3 @@ -0,0 +1,99 @@
   167.4 +/**
   167.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   167.6 + *
   167.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   167.8 + *
   167.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  167.10 + * Other names may be trademarks of their respective owners.
  167.11 + *
  167.12 + * The contents of this file are subject to the terms of either the GNU
  167.13 + * General Public License Version 2 only ("GPL") or the Common
  167.14 + * Development and Distribution License("CDDL") (collectively, the
  167.15 + * "License"). You may not use this file except in compliance with the
  167.16 + * License. You can obtain a copy of the License at
  167.17 + * http://www.netbeans.org/cddl-gplv2.html
  167.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  167.19 + * specific language governing permissions and limitations under the
  167.20 + * License.  When distributing the software, include this License Header
  167.21 + * Notice in each file and include the License file at
  167.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  167.23 + * particular file as subject to the "Classpath" exception as provided
  167.24 + * by Oracle in the GPL Version 2 section of the License file that
  167.25 + * accompanied this code. If applicable, add the following below the
  167.26 + * License Header, with the fields enclosed by brackets [] replaced by
  167.27 + * your own identifying information:
  167.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  167.29 + *
  167.30 + * Contributor(s):
  167.31 + *
  167.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  167.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  167.34 + *
  167.35 + * If you wish your version of this file to be governed by only the CDDL
  167.36 + * or only the GPL Version 2, indicate your decision by adding
  167.37 + * "[Contributor] elects to include this software in this distribution
  167.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  167.39 + * single choice of license, a recipient has the option to distribute
  167.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  167.41 + * to extend the choice of license to its licensees as provided above.
  167.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  167.43 + * Version 2 license, then the option applies only if the new code is
  167.44 + * made subject to such option by the copyright holder.
  167.45 + */
  167.46 +package org.netbeans.html.archetype.test;
  167.47 +
  167.48 +import java.io.File;
  167.49 +import java.util.Properties;
  167.50 +import org.apache.maven.it.Verifier;
  167.51 +import org.testng.annotations.Test;
  167.52 +import static org.testng.Assert.*;
  167.53 +
  167.54 +/**
  167.55 + *
  167.56 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  167.57 + */
  167.58 +public class VerifyArchetypeTest {
  167.59 +    @Test public void projectCompiles() throws Exception {
  167.60 +        final File dir = new File("target/tests/fxcompile/").getAbsoluteFile();
  167.61 +        generateFromArchetype(dir);
  167.62 +        
  167.63 +        File created = new File(dir, "o-a-test");
  167.64 +        assertTrue(created.isDirectory(), "Project created");
  167.65 +        assertTrue(new File(created, "pom.xml").isFile(), "Pom file is in there");
  167.66 +        
  167.67 +        Verifier v = new Verifier(created.getAbsolutePath());
  167.68 +        v.executeGoal("verify");
  167.69 +        
  167.70 +        v.verifyErrorFreeLog();
  167.71 +        
  167.72 +        for (String l : v.loadFile(v.getBasedir(), v.getLogFileName(), false)) {
  167.73 +            if (l.contains("j2js")) {
  167.74 +                fail("No pre-compilaton:\n" + l);
  167.75 +            }
  167.76 +        }
  167.77 +        
  167.78 +        v.verifyTextInLog("fxcompile/o-a-test/target/o-a-test-1.0-SNAPSHOT-html.java.net.zip");
  167.79 +    }
  167.80 +    
  167.81 +    private Verifier generateFromArchetype(final File dir, String... params) throws Exception {
  167.82 +        Verifier v = new Verifier(dir.getAbsolutePath());
  167.83 +        v.setAutoclean(false);
  167.84 +        v.setLogFileName("generate.log");
  167.85 +        v.deleteDirectory("");
  167.86 +        dir.mkdirs();
  167.87 +        Properties sysProp = v.getSystemProperties();
  167.88 +        sysProp.put("groupId", "org.apidesign.test");
  167.89 +        sysProp.put("artifactId", "o-a-test");
  167.90 +        sysProp.put("package", "org.apidesign.test.oat");
  167.91 +        sysProp.put("archetypeGroupId", "org.apidesign.html");
  167.92 +        sysProp.put("archetypeArtifactId", "knockout4j-archetype");
  167.93 +        sysProp.put("archetypeVersion", ArchetypeVersionTest.findCurrentVersion());
  167.94 +        
  167.95 +        for (String p : params) {
  167.96 +            v.addCliOption(p);
  167.97 +        }
  167.98 +        v.executeGoal("archetype:generate");
  167.99 +        v.verifyErrorFreeLog();
 167.100 +        return v;
 167.101 +    }
 167.102 +}
   168.1 --- a/ko-archetype/pom.xml	Mon Dec 16 17:16:02 2013 +0100
   168.2 +++ b/ko-archetype/pom.xml	Mon Dec 16 17:16:40 2013 +0100
   168.3 @@ -2,11 +2,11 @@
   168.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">
   168.5    <modelVersion>4.0.0</modelVersion>
   168.6    <parent>
   168.7 -    <artifactId>html</artifactId>
   168.8 -    <groupId>org.apidesign</groupId>
   168.9 +    <groupId>org.netbeans.html</groupId>
  168.10 +    <artifactId>pom</artifactId>
  168.11      <version>0.7-SNAPSHOT</version>
  168.12    </parent>
  168.13 -  <groupId>org.apidesign.html</groupId>
  168.14 +  <groupId>org.netbeans.html</groupId>
  168.15    <artifactId>knockout4j-archetype</artifactId>
  168.16    <version>0.7-SNAPSHOT</version>
  168.17    <packaging>jar</packaging>
   169.1 --- a/ko-archetype/src/main/java/org/apidesign/html/archetype/package-info.java	Mon Dec 16 17:16:02 2013 +0100
   169.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   169.3 @@ -1,21 +0,0 @@
   169.4 -/**
   169.5 - * HTML via Java(tm) Language Bindings
   169.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   169.7 - *
   169.8 - * This program is free software: you can redistribute it and/or modify
   169.9 - * it under the terms of the GNU General Public License as published by
  169.10 - * the Free Software Foundation, version 2 of the License.
  169.11 - *
  169.12 - * This program is distributed in the hope that it will be useful,
  169.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  169.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  169.15 - * GNU General Public License for more details. apidesign.org
  169.16 - * designates this particular file as subject to the
  169.17 - * "Classpath" exception as provided by apidesign.org
  169.18 - * in the License file that accompanied this code.
  169.19 - *
  169.20 - * You should have received a copy of the GNU General Public License
  169.21 - * along with this program. Look for COPYING file in the top folder.
  169.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  169.23 - */
  169.24 -package org.apidesign.html.archetype;
   170.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   170.2 +++ b/ko-archetype/src/main/java/org/netbeans/html/archetype/package-info.java	Mon Dec 16 17:16:40 2013 +0100
   170.3 @@ -0,0 +1,43 @@
   170.4 +/**
   170.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   170.6 + *
   170.7 + * Copyright 1997-2010 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.archetype;
   171.1 --- a/ko-archetype/src/main/resources/archetype-resources/pom.xml	Mon Dec 16 17:16:02 2013 +0100
   171.2 +++ b/ko-archetype/src/main/resources/archetype-resources/pom.xml	Mon Dec 16 17:16:40 2013 +0100
   171.3 @@ -101,24 +101,24 @@
   171.4    </build>
   171.5    <dependencies>
   171.6      <dependency>
   171.7 -        <groupId>org.apidesign.html</groupId>
   171.8 +        <groupId>org.netbeans.html</groupId>
   171.9          <artifactId>net.java.html.json</artifactId>
  171.10          <version>\${net.java.html.version}</version>
  171.11      </dependency>
  171.12      <dependency>
  171.13 -        <groupId>org.apidesign.html</groupId>
  171.14 +        <groupId>org.netbeans.html</groupId>
  171.15          <artifactId>net.java.html.boot</artifactId>
  171.16          <version>\${net.java.html.version}</version>
  171.17      </dependency>
  171.18      <dependency>
  171.19 -        <groupId>org.apidesign.html</groupId>
  171.20 +        <groupId>org.netbeans.html</groupId>
  171.21          <artifactId>ko-fx</artifactId>
  171.22          <version>\${net.java.html.version}</version>
  171.23          <scope>runtime</scope>
  171.24      </dependency>
  171.25      <dependency>
  171.26 -        <groupId>org.apidesign.html</groupId>
  171.27 -        <artifactId>boot-fx</artifactId>
  171.28 +        <groupId>org.netbeans.html</groupId>
  171.29 +        <artifactId>net.java.html.boot.fx</artifactId>
  171.30          <version>\${net.java.html.version}</version>
  171.31          <scope>runtime</scope>
  171.32      </dependency>
   172.1 --- a/ko-fx/pom.xml	Mon Dec 16 17:16:02 2013 +0100
   172.2 +++ b/ko-fx/pom.xml	Mon Dec 16 17:16:40 2013 +0100
   172.3 @@ -2,11 +2,11 @@
   172.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">
   172.5    <modelVersion>4.0.0</modelVersion>
   172.6    <parent>
   172.7 -    <groupId>org.apidesign</groupId>
   172.8 -    <artifactId>html</artifactId>
   172.9 +    <groupId>org.netbeans.html</groupId>
  172.10 +    <artifactId>pom</artifactId>
  172.11      <version>0.7-SNAPSHOT</version>
  172.12    </parent>
  172.13 -  <groupId>org.apidesign.html</groupId>
  172.14 +  <groupId>org.netbeans.html</groupId>
  172.15    <artifactId>ko-fx</artifactId>
  172.16    <version>0.7-SNAPSHOT</version>
  172.17    <packaging>bundle</packaging>
  172.18 @@ -14,6 +14,7 @@
  172.19    <url>http://maven.apache.org</url>
  172.20    <properties>
  172.21      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  172.22 +    <bundleSymbolicName>org.netbeans.html.ko-fx</bundleSymbolicName>
  172.23    </properties>
  172.24    <build>
  172.25        <plugins>
  172.26 @@ -52,7 +53,7 @@
  172.27          <artifactId>org.json-osgi</artifactId>
  172.28      </dependency>
  172.29      <dependency>
  172.30 -      <groupId>org.apidesign.html</groupId>
  172.31 +      <groupId>org.netbeans.html</groupId>
  172.32        <artifactId>net.java.html.json</artifactId>
  172.33        <version>${project.version}</version>
  172.34      </dependency>
  172.35 @@ -73,14 +74,14 @@
  172.36        <scope>provided</scope>
  172.37      </dependency>
  172.38      <dependency>
  172.39 -      <groupId>org.apidesign.html</groupId>
  172.40 +      <groupId>org.netbeans.html</groupId>
  172.41        <artifactId>net.java.html.boot</artifactId>
  172.42        <version>${project.version}</version>
  172.43        <type>jar</type>
  172.44      </dependency>
  172.45      <dependency>
  172.46        <groupId>${project.groupId}</groupId>
  172.47 -      <artifactId>boot-fx</artifactId>
  172.48 +      <artifactId>net.java.html.boot.fx</artifactId>
  172.49        <version>${project.version}</version>
  172.50        <scope>test</scope>
  172.51      </dependency>
   173.1 --- a/ko-fx/src/main/java/org/apidesign/html/kofx/Console.java	Mon Dec 16 17:16:02 2013 +0100
   173.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   173.3 @@ -1,59 +0,0 @@
   173.4 -/**
   173.5 - * HTML via Java(tm) Language Bindings
   173.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   173.7 - *
   173.8 - * This program is free software: you can redistribute it and/or modify
   173.9 - * it under the terms of the GNU General Public License as published by
  173.10 - * the Free Software Foundation, version 2 of the License.
  173.11 - *
  173.12 - * This program is distributed in the hope that it will be useful,
  173.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  173.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  173.15 - * GNU General Public License for more details. apidesign.org
  173.16 - * designates this particular file as subject to the
  173.17 - * "Classpath" exception as provided by apidesign.org
  173.18 - * in the License file that accompanied this code.
  173.19 - *
  173.20 - * You should have received a copy of the GNU General Public License
  173.21 - * along with this program. Look for COPYING file in the top folder.
  173.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  173.23 - */
  173.24 -package org.apidesign.html.kofx;
  173.25 -
  173.26 -import java.util.logging.Level;
  173.27 -import java.util.logging.Logger;
  173.28 -import net.java.html.js.JavaScriptBody;
  173.29 -
  173.30 -/** This is an implementation package - just
  173.31 - * include its JAR on classpath and use official {@link Context} API
  173.32 - * to access the functionality.
  173.33 - * <p>
  173.34 - * Redirects JavaScript's messages to Java's {@link Logger}.
  173.35 - *
  173.36 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  173.37 - */
  173.38 -final class Console {
  173.39 -    private static final Logger LOG = Logger.getLogger(Console.class.getName());
  173.40 -    
  173.41 -    private Console() {
  173.42 -    }
  173.43 -
  173.44 -    static void register() {
  173.45 -        registerImpl("log", Level.INFO);
  173.46 -        registerImpl("info", Level.INFO);
  173.47 -        registerImpl("warn", Level.WARNING);
  173.48 -        registerImpl("error", Level.SEVERE);
  173.49 -    }
  173.50 -    
  173.51 -    @JavaScriptBody(args = { "attr", "l" }, 
  173.52 -        javacall = true, body = 
  173.53 -        "  window.console[attr] = function(m) {\n"
  173.54 -      + "    @org.apidesign.html.kofx.Console::log(Ljava/util/logging/Level;Ljava/lang/String;)(l, m);\n"
  173.55 -      + "  };\n"
  173.56 -    )
  173.57 -    private static native void registerImpl(String attr, Level l);
  173.58 -    
  173.59 -    static void log(Level l, String msg) {
  173.60 -        LOG.log(l, msg);
  173.61 -    }
  173.62 -}
   174.1 --- a/ko-fx/src/main/java/org/apidesign/html/kofx/FXContext.java	Mon Dec 16 17:16:02 2013 +0100
   174.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   174.3 @@ -1,200 +0,0 @@
   174.4 -/**
   174.5 - * HTML via Java(tm) Language Bindings
   174.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   174.7 - *
   174.8 - * This program is free software: you can redistribute it and/or modify
   174.9 - * it under the terms of the GNU General Public License as published by
  174.10 - * the Free Software Foundation, version 2 of the License.
  174.11 - *
  174.12 - * This program is distributed in the hope that it will be useful,
  174.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  174.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  174.15 - * GNU General Public License for more details. apidesign.org
  174.16 - * designates this particular file as subject to the
  174.17 - * "Classpath" exception as provided by apidesign.org
  174.18 - * in the License file that accompanied this code.
  174.19 - *
  174.20 - * You should have received a copy of the GNU General Public License
  174.21 - * along with this program. Look for COPYING file in the top folder.
  174.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  174.23 - */
  174.24 -package org.apidesign.html.kofx;
  174.25 -
  174.26 -import java.io.Closeable;
  174.27 -import java.io.IOException;
  174.28 -import java.io.InputStream;
  174.29 -import java.util.ServiceLoader;
  174.30 -import java.util.logging.Logger;
  174.31 -import javafx.application.Platform;
  174.32 -import net.java.html.js.JavaScriptBody;
  174.33 -import netscape.javascript.JSObject;
  174.34 -import org.apidesign.html.boot.spi.Fn;
  174.35 -import org.apidesign.html.context.spi.Contexts;
  174.36 -import org.apidesign.html.json.spi.FunctionBinding;
  174.37 -import org.apidesign.html.json.spi.JSONCall;
  174.38 -import org.apidesign.html.json.spi.PropertyBinding;
  174.39 -import org.apidesign.html.json.spi.Technology;
  174.40 -import org.apidesign.html.json.spi.Transfer;
  174.41 -import org.apidesign.html.json.spi.WSTransfer;
  174.42 -import org.openide.util.lookup.ServiceProvider;
  174.43 -
  174.44 -/** This is an implementation package - just
  174.45 - * include its JAR on classpath and use official {@link Context} API
  174.46 - * to access the functionality.
  174.47 - * <p>
  174.48 - * Registers {@link ContextProvider}, so {@link ServiceLoader} can find it.
  174.49 - *
  174.50 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  174.51 - */
  174.52 -public final class FXContext
  174.53 -implements Technology.BatchInit<JSObject>, Transfer, WSTransfer<LoadWS> {
  174.54 -    static final Logger LOG = Logger.getLogger(FXContext.class.getName());
  174.55 -    private static Boolean javaScriptEnabled;
  174.56 -    private final Fn.Presenter browserContext;
  174.57 -
  174.58 -    public FXContext(Fn.Presenter browserContext) {
  174.59 -        this.browserContext = browserContext;
  174.60 -    }
  174.61 -    
  174.62 -    @JavaScriptBody(args = {}, body = "return true;")
  174.63 -    private static boolean isJavaScriptEnabledJs() {
  174.64 -        return false;
  174.65 -    }
  174.66 -    
  174.67 -    static boolean isJavaScriptEnabled() {
  174.68 -        if (javaScriptEnabled != null) {
  174.69 -            return javaScriptEnabled;
  174.70 -        }
  174.71 -        return javaScriptEnabled = isJavaScriptEnabledJs();
  174.72 -    }
  174.73 -
  174.74 -    final boolean areWebSocketsSupported() {
  174.75 -        return LoadWS.isSupported();
  174.76 -    }
  174.77 -
  174.78 -
  174.79 -    @Override
  174.80 -    public JSObject wrapModel(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
  174.81 -        String[] propNames = new String[propArr.length];
  174.82 -        boolean[] propReadOnly = new boolean[propArr.length];
  174.83 -        Object[] propValues = new Object[propArr.length];
  174.84 -        for (int i = 0; i < propNames.length; i++) {
  174.85 -            propNames[i] = propArr[i].getPropertyName();
  174.86 -            propReadOnly[i] = propArr[i].isReadOnly();
  174.87 -            propValues[i] = propArr[i].getValue();
  174.88 -        }
  174.89 -        String[] funcNames = new String[funcArr.length];
  174.90 -        for (int i = 0; i < funcNames.length; i++) {
  174.91 -            funcNames[i] = funcArr[i].getFunctionName();
  174.92 -        }
  174.93 -        
  174.94 -        return Knockout.wrapModel(model, 
  174.95 -            propNames, propReadOnly, Knockout.toArray(propValues), propArr, 
  174.96 -            funcNames, funcArr
  174.97 -        );
  174.98 -    }
  174.99 -    
 174.100 -    @Override
 174.101 -    public JSObject wrapModel(Object model) {
 174.102 -        throw new UnsupportedOperationException();
 174.103 -    }
 174.104 -
 174.105 -    @Override
 174.106 -    public void bind(PropertyBinding b, Object model, JSObject data) {
 174.107 -        throw new UnsupportedOperationException();
 174.108 -    }
 174.109 -
 174.110 -    @Override
 174.111 -    public void valueHasMutated(JSObject data, String propertyName) {
 174.112 -        Knockout.valueHasMutated(data, propertyName);
 174.113 -    }
 174.114 -
 174.115 -    @Override
 174.116 -    public void expose(FunctionBinding fb, Object model, JSObject d) {
 174.117 -        throw new UnsupportedOperationException();
 174.118 -    }
 174.119 -
 174.120 -    @Override
 174.121 -    public void applyBindings(JSObject data) {
 174.122 -        Knockout.applyBindings(data);
 174.123 -    }
 174.124 -
 174.125 -    @Override
 174.126 -    public Object wrapArray(Object[] arr) {
 174.127 -        return Knockout.toArray(arr);
 174.128 -    }
 174.129 -
 174.130 -    @Override
 174.131 -    public void extract(Object obj, String[] props, Object[] values) {
 174.132 -        LoadJSON.extractJSON(obj, props, values);
 174.133 -    }
 174.134 -
 174.135 -    @Override
 174.136 -    public void loadJSON(final JSONCall call) {
 174.137 -        LoadJSON.loadJSON(call);
 174.138 -    }
 174.139 -
 174.140 -    @Override
 174.141 -    public <M> M toModel(Class<M> modelClass, Object data) {
 174.142 -        if (data instanceof JSObject) {
 174.143 -            data = ((JSObject)data).getMember("ko-fx.model"); // NOI18N
 174.144 -        }
 174.145 -        return modelClass.cast(data);
 174.146 -    }
 174.147 -
 174.148 -    @Override
 174.149 -    public Object toJSON(InputStream is) throws IOException {
 174.150 -        return LoadJSON.parse(is);
 174.151 -    }
 174.152 -
 174.153 -    @Override
 174.154 -    public void runSafe(final Runnable r) {
 174.155 -        class Wrap implements Runnable {
 174.156 -            @Override public void run() {
 174.157 -                try (Closeable c = Fn.activate(browserContext)) {
 174.158 -                    r.run();
 174.159 -                } catch (IOException ex) {
 174.160 -                    // cannot be thrown
 174.161 -                }
 174.162 -            }
 174.163 -        }
 174.164 -        Wrap w = new Wrap();
 174.165 -        
 174.166 -        if (Platform.isFxApplicationThread()) {
 174.167 -            w.run();
 174.168 -        } else {
 174.169 -            Platform.runLater(w);
 174.170 -        }
 174.171 -    }
 174.172 -
 174.173 -    @Override
 174.174 -    public LoadWS open(String url, JSONCall onReply) {
 174.175 -        return new LoadWS(onReply, url);
 174.176 -    }
 174.177 -
 174.178 -    @Override
 174.179 -    public void send(LoadWS socket, JSONCall data) {
 174.180 -        socket.send(data);
 174.181 -    }
 174.182 -
 174.183 -    @Override
 174.184 -    public void close(LoadWS socket) {
 174.185 -        socket.close();
 174.186 -    }
 174.187 -    
 174.188 -    @ServiceProvider(service = Contexts.Provider.class)
 174.189 -    public static final class Prvdr implements Contexts.Provider {
 174.190 -        @Override
 174.191 -        public void fillContext(Contexts.Builder context, Class<?> requestor) {
 174.192 -            if (isJavaScriptEnabled()) {
 174.193 -                FXContext c = new FXContext(Fn.activePresenter());
 174.194 -                
 174.195 -                context.register(Technology.class, c, 100);
 174.196 -                context.register(Transfer.class, c, 100);
 174.197 -                if (c.areWebSocketsSupported()) {
 174.198 -                    context.register(WSTransfer.class, c, 100);
 174.199 -                }
 174.200 -            }
 174.201 -        }
 174.202 -    }
 174.203 -}
   175.1 --- a/ko-fx/src/main/java/org/apidesign/html/kofx/Knockout.java	Mon Dec 16 17:16:02 2013 +0100
   175.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   175.3 @@ -1,123 +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.kofx;
  175.25 -
  175.26 -import net.java.html.js.JavaScriptBody;
  175.27 -import net.java.html.js.JavaScriptResource;
  175.28 -import net.java.html.json.Model;
  175.29 -import netscape.javascript.JSObject;
  175.30 -import org.apidesign.html.json.spi.FunctionBinding;
  175.31 -import org.apidesign.html.json.spi.PropertyBinding;
  175.32 -
  175.33 -/** This is an implementation package - just
  175.34 - * include its JAR on classpath and use official {@link Context} API
  175.35 - * to access the functionality.
  175.36 - * <p>
  175.37 - * Provides binding between {@link Model models} and knockout.js running
  175.38 - * inside a JavaFX WebView. 
  175.39 - *
  175.40 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  175.41 - */
  175.42 -@JavaScriptResource("knockout-2.2.1.js")
  175.43 -final class Knockout {
  175.44 -    static final JSObject KObject;
  175.45 -    static {
  175.46 -        Console.register();
  175.47 -        KObject = (JSObject) kObj();
  175.48 -    }
  175.49 -
  175.50 -    static Object toArray(Object[] arr) {
  175.51 -        return KObject.call("array", arr);
  175.52 -    }
  175.53 -    
  175.54 -    @JavaScriptBody(args = { "model", "prop" }, body =
  175.55 -          "if (model) {\n"
  175.56 -        + "  var koProp = model[prop];\n"
  175.57 -        + "  if (koProp && koProp['valueHasMutated']) {\n"
  175.58 -        + "    koProp['valueHasMutated']();\n"
  175.59 -        + "  }\n"
  175.60 -        + "}\n"
  175.61 -    )
  175.62 -    public native static void valueHasMutated(JSObject model, String prop);
  175.63 -
  175.64 -    @JavaScriptBody(args = { "bindings" }, body = "ko.applyBindings(bindings);")
  175.65 -    native static void applyBindings(Object bindings);
  175.66 -    
  175.67 -    @JavaScriptBody(args = {}, body =
  175.68 -              "  var k = {};"
  175.69 -            + "  k.array= function() {"
  175.70 -            + "    return Array.prototype.slice.call(arguments);"
  175.71 -            + "  };"
  175.72 -            + "  return k;"
  175.73 -    )
  175.74 -    private static native Object kObj();
  175.75 -        
  175.76 -        
  175.77 -    @JavaScriptBody(
  175.78 -        javacall = true,
  175.79 -        args = {"model", "propNames", "propReadOnly", "propValues", "propArr", "funcNames", "funcArr"},
  175.80 -        body
  175.81 -        = "var ret = {};\n"
  175.82 -        + "ret['ko-fx.model'] = model;\n"
  175.83 -        + "function koComputed(name, readOnly, value, prop) {\n"
  175.84 -        + "  function realGetter() {\n"
  175.85 -        + "    try {"
  175.86 -        + "      var v = prop.@org.apidesign.html.json.spi.PropertyBinding::getValue()();"
  175.87 -        + "      return v;"
  175.88 -        + "    } catch (e) {"
  175.89 -        + "      alert(\"Cannot call getValue on \" + model + \" prop: \" + name + \" error: \" + e);"
  175.90 -        + "    }"
  175.91 -        + "  }\n"
  175.92 -        + "  var activeGetter = function() { return value; };\n"
  175.93 -        + "  var bnd = {"
  175.94 -        + "    read: function() {"
  175.95 -        + "      var r = activeGetter();"
  175.96 -        + "      activeGetter = realGetter;"
  175.97 -        + "      return r;"
  175.98 -        + "    },"
  175.99 -        + "    owner: ret\n"
 175.100 -        + "  };\n"
 175.101 -        + "  if (!readOnly) {\n"
 175.102 -        + "    bnd.write = function(val) {\n"
 175.103 -        + "      prop.@org.apidesign.html.json.spi.PropertyBinding::setValue(Ljava/lang/Object;)(val);\n"
 175.104 -        + "    };"
 175.105 -        + "  };"
 175.106 -        + "  ret[name] = ko.computed(bnd);"
 175.107 -        + "}\n"
 175.108 -        + "for (var i = 0; i < propNames.length; i++) {\n"
 175.109 -        + "  koComputed(propNames[i], propReadOnly[i], propValues[i], propArr[i]);\n"
 175.110 -        + "}\n"
 175.111 -        + "function koExpose(name, func) {\n"
 175.112 -        + "  ret[name] = function(data, ev) {\n"
 175.113 -        + "    func.@org.apidesign.html.json.spi.FunctionBinding::call(Ljava/lang/Object;Ljava/lang/Object;)(data, ev);\n"
 175.114 -        + "  };\n"
 175.115 -        + "}\n"
 175.116 -        + "for (var i = 0; i < funcNames.length; i++) {\n"
 175.117 -        + "  koExpose(funcNames[i], funcArr[i]);\n"
 175.118 -        + "}\n"
 175.119 -        + "return ret;\n"
 175.120 -        )
 175.121 -    static native JSObject wrapModel(
 175.122 -        Object model,
 175.123 -        String[] propNames, boolean[] propReadOnly, Object propValues, PropertyBinding[] propArr,
 175.124 -        String[] funcNames, FunctionBinding[] funcArr
 175.125 -    );
 175.126 -}
   176.1 --- a/ko-fx/src/main/java/org/apidesign/html/kofx/LoadJSON.java	Mon Dec 16 17:16:02 2013 +0100
   176.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   176.3 @@ -1,245 +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.kofx;
  176.25 -
  176.26 -import java.io.IOException;
  176.27 -import java.io.InputStream;
  176.28 -import java.io.InputStreamReader;
  176.29 -import java.io.OutputStream;
  176.30 -import java.io.PushbackInputStream;
  176.31 -import java.io.Reader;
  176.32 -import java.net.HttpURLConnection;
  176.33 -import java.net.MalformedURLException;
  176.34 -import java.net.URL;
  176.35 -import java.net.URLConnection;
  176.36 -import java.util.Iterator;
  176.37 -import java.util.concurrent.Executor;
  176.38 -import java.util.concurrent.Executors;
  176.39 -import java.util.concurrent.ThreadFactory;
  176.40 -import java.util.logging.Level;
  176.41 -import java.util.logging.Logger;
  176.42 -import javafx.application.Platform;
  176.43 -import net.java.html.js.JavaScriptBody;
  176.44 -import netscape.javascript.JSObject;
  176.45 -import org.apidesign.html.json.spi.JSONCall;
  176.46 -import org.json.JSONArray;
  176.47 -import org.json.JSONException;
  176.48 -import org.json.JSONObject;
  176.49 -import org.json.JSONTokener;
  176.50 -
  176.51 -/** This is an implementation package - just
  176.52 - * include its JAR on classpath and use official {@link Context} API
  176.53 - * to access the functionality.
  176.54 - *
  176.55 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  176.56 - */
  176.57 -final class LoadJSON implements Runnable {
  176.58 -    private static final Logger LOG = FXContext.LOG;
  176.59 -    private static final Executor REQ = Executors.newCachedThreadPool(new ThreadFactory() {
  176.60 -        @Override
  176.61 -        public Thread newThread(Runnable runnable) {
  176.62 -            Thread thread = Executors.defaultThreadFactory().newThread(runnable);
  176.63 -            thread.setDaemon(true);
  176.64 -            return thread;
  176.65 -        }
  176.66 -    });
  176.67 -
  176.68 -    private final JSONCall call;
  176.69 -    private final URL base;
  176.70 -    private Throwable error;
  176.71 -    private Object json;
  176.72 -
  176.73 -
  176.74 -    private LoadJSON(JSONCall call) {
  176.75 -        this.call = call;
  176.76 -        URL b;
  176.77 -        try {
  176.78 -            b = new URL(findBaseURL());
  176.79 -        } catch (MalformedURLException ex) {
  176.80 -            LOG.log(Level.SEVERE, "Can't find base url for " + call.composeURL("dummy"), ex);
  176.81 -            b = null;
  176.82 -        }
  176.83 -        this.base = b;
  176.84 -    }
  176.85 -
  176.86 -    public static void loadJSON(JSONCall call) {
  176.87 -        assert !"WebSocket".equals(call.getMethod());
  176.88 -        REQ.execute(new LoadJSON((call)));
  176.89 -    }
  176.90 -
  176.91 -    @Override
  176.92 -    public void run() {
  176.93 -        if (Platform.isFxApplicationThread()) {
  176.94 -            if (error != null) {
  176.95 -                call.notifyError(error);
  176.96 -            } else {
  176.97 -                call.notifySuccess(json);
  176.98 -            }
  176.99 -            return;
 176.100 -        }
 176.101 -        final String url;
 176.102 -        if (call.isJSONP()) {
 176.103 -            url = call.composeURL("dummy");
 176.104 -        } else {
 176.105 -            url = call.composeURL(null);
 176.106 -        }
 176.107 -        try {
 176.108 -            final URL u = new URL(base, url.replace(" ", "%20"));
 176.109 -            URLConnection conn = u.openConnection();
 176.110 -            if (conn instanceof HttpURLConnection) {
 176.111 -                HttpURLConnection huc = (HttpURLConnection) conn;
 176.112 -                if (call.getMethod() != null) {
 176.113 -                    huc.setRequestMethod(call.getMethod());
 176.114 -                }
 176.115 -                if (call.isDoOutput()) {
 176.116 -                    huc.setDoOutput(true);
 176.117 -                    final OutputStream os = huc.getOutputStream();
 176.118 -                    call.writeData(os);
 176.119 -                    os.flush();
 176.120 -                }
 176.121 -            }
 176.122 -            final PushbackInputStream is = new PushbackInputStream(
 176.123 -                conn.getInputStream(), 1
 176.124 -            );
 176.125 -            boolean array = false;
 176.126 -            boolean string = false;
 176.127 -            if (call.isJSONP()) {
 176.128 -                for (;;) {
 176.129 -                    int ch = is.read();
 176.130 -                    if (ch == -1) {
 176.131 -                        break;
 176.132 -                    }
 176.133 -                    if (ch == '[') {
 176.134 -                        is.unread(ch);
 176.135 -                        array = true;
 176.136 -                        break;
 176.137 -                    }
 176.138 -                    if (ch == '{') {
 176.139 -                        is.unread(ch);
 176.140 -                        break;
 176.141 -                    }
 176.142 -                }
 176.143 -            } else {
 176.144 -                int ch = is.read();
 176.145 -                if (ch == -1) {
 176.146 -                    string = true;
 176.147 -                } else {
 176.148 -                    array = ch == '[';
 176.149 -                    is.unread(ch);
 176.150 -                    if (!array && ch != '{') {
 176.151 -                        string = true;
 176.152 -                    }
 176.153 -                }
 176.154 -            }
 176.155 -            try {
 176.156 -                if (string) {
 176.157 -                    throw new JSONException("");
 176.158 -                }
 176.159 -                Reader r = new InputStreamReader(is, "UTF-8");
 176.160 -
 176.161 -                JSONTokener tok = new JSONTokener(r);
 176.162 -                Object obj;
 176.163 -                obj = array ? new JSONArray(tok) : new JSONObject(tok);
 176.164 -                json = convertToArray(obj);
 176.165 -            } catch (JSONException ex) {
 176.166 -                Reader r = new InputStreamReader(is, "UTF-8");
 176.167 -                StringBuilder sb = new StringBuilder();
 176.168 -                for (;;) {
 176.169 -                    int ch = r.read();
 176.170 -                    if (ch == -1) {
 176.171 -                        break;
 176.172 -                    }
 176.173 -                    sb.append((char)ch);
 176.174 -                }
 176.175 -                json = sb.toString();
 176.176 -            }
 176.177 -        } catch (IOException ex) {
 176.178 -            error = ex;
 176.179 -        } finally {
 176.180 -            Platform.runLater(this);
 176.181 -        }
 176.182 -    }
 176.183 -
 176.184 -    static Object convertToArray(Object o) throws JSONException {
 176.185 -        if (o instanceof JSONArray) {
 176.186 -            JSONArray ja = (JSONArray)o;
 176.187 -            Object[] arr = new Object[ja.length()];
 176.188 -            for (int i = 0; i < arr.length; i++) {
 176.189 -                arr[i] = convertToArray(ja.get(i));
 176.190 -            }
 176.191 -            return arr;
 176.192 -        } else if (o instanceof JSONObject) {
 176.193 -            JSONObject obj = (JSONObject)o;
 176.194 -            Iterator it = obj.keys();
 176.195 -            while (it.hasNext()) {
 176.196 -                String key = (String)it.next();
 176.197 -                obj.put(key, convertToArray(obj.get(key)));
 176.198 -            }
 176.199 -            return obj;
 176.200 -        } else {
 176.201 -            return o;
 176.202 -        }
 176.203 -    }
 176.204 -    
 176.205 -    public static void extractJSON(Object jsonObject, String[] props, Object[] values) {
 176.206 -        if (jsonObject instanceof JSONObject) {
 176.207 -            JSONObject obj = (JSONObject)jsonObject;
 176.208 -            for (int i = 0; i < props.length; i++) {
 176.209 -                try {
 176.210 -                    values[i] = obj.has(props[i]) ? obj.get(props[i]) : null;
 176.211 -                } catch (JSONException ex) {
 176.212 -                    LoadJSON.LOG.log(Level.SEVERE, "Can't read " + props[i] + " from " + jsonObject, ex);
 176.213 -                }
 176.214 -            }
 176.215 -        }
 176.216 -        if (jsonObject instanceof JSObject) {
 176.217 -            JSObject obj = (JSObject)jsonObject;
 176.218 -            for (int i = 0; i < props.length; i++) {
 176.219 -                Object val = obj.getMember(props[i]);
 176.220 -                values[i] = isDefined(val) ? val : null;
 176.221 -            }
 176.222 -        }
 176.223 -    }
 176.224 -    
 176.225 -    public static Object parse(InputStream is) throws IOException {
 176.226 -        try {
 176.227 -            InputStreamReader r = new InputStreamReader(is, "UTF-8");
 176.228 -            JSONTokener t = new JSONTokener(r);
 176.229 -            return new JSONObject(t);
 176.230 -        } catch (JSONException ex) {
 176.231 -            throw new IOException(ex);
 176.232 -        }
 176.233 -    }
 176.234 -
 176.235 -    @JavaScriptBody(args = {  }, body = 
 176.236 -          "var h;"
 176.237 -        + "if (!!window && !!window.location && !!window.location.href)\n"
 176.238 -        + "  h = window.location.href;\n"
 176.239 -        + "else "
 176.240 -        + "  h = null;"
 176.241 -        + "return h;\n"
 176.242 -    )
 176.243 -    private static native String findBaseURL();
 176.244 -    
 176.245 -    private static boolean isDefined(Object val) {
 176.246 -        return !"undefined".equals(val);
 176.247 -    }
 176.248 -}
   177.1 --- a/ko-fx/src/main/java/org/apidesign/html/kofx/LoadWS.java	Mon Dec 16 17:16:02 2013 +0100
   177.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   177.3 @@ -1,127 +0,0 @@
   177.4 -/**
   177.5 - * HTML via Java(tm) Language Bindings
   177.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   177.7 - *
   177.8 - * This program is free software: you can redistribute it and/or modify
   177.9 - * it under the terms of the GNU General Public License as published by
  177.10 - * the Free Software Foundation, version 2 of the License.
  177.11 - *
  177.12 - * This program is distributed in the hope that it will be useful,
  177.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  177.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  177.15 - * GNU General Public License for more details. apidesign.org
  177.16 - * designates this particular file as subject to the
  177.17 - * "Classpath" exception as provided by apidesign.org
  177.18 - * in the License file that accompanied this code.
  177.19 - *
  177.20 - * You should have received a copy of the GNU General Public License
  177.21 - * along with this program. Look for COPYING file in the top folder.
  177.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  177.23 - */
  177.24 -package org.apidesign.html.kofx;
  177.25 -
  177.26 -import net.java.html.js.JavaScriptBody;
  177.27 -import org.apidesign.html.json.spi.JSONCall;
  177.28 -import org.json.JSONArray;
  177.29 -import org.json.JSONException;
  177.30 -import org.json.JSONObject;
  177.31 -import org.json.JSONTokener;
  177.32 -
  177.33 -/** Communication with WebSockets for WebView 1.8.
  177.34 - *
  177.35 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  177.36 - */
  177.37 -final class LoadWS {
  177.38 -    private static final boolean SUPPORTED = isWebSocket();
  177.39 -    private final Object ws;
  177.40 -    private final JSONCall call;
  177.41 -
  177.42 -    LoadWS(JSONCall first, String url) {
  177.43 -        call = first;
  177.44 -        ws = initWebSocket(this, url);
  177.45 -        if (ws == null) {
  177.46 -            first.notifyError(new IllegalArgumentException("Wrong URL: " + url));
  177.47 -        }
  177.48 -    }
  177.49 -    
  177.50 -    static boolean isSupported() {
  177.51 -        return SUPPORTED;
  177.52 -    }
  177.53 -    
  177.54 -    void send(JSONCall call) {
  177.55 -        push(call);
  177.56 -    }
  177.57 -    
  177.58 -    private synchronized void push(JSONCall call) {
  177.59 -        send(ws, call.getMessage());
  177.60 -    }
  177.61 -
  177.62 -    void onOpen(Object ev) {
  177.63 -        if (!call.isDoOutput()) {
  177.64 -            call.notifySuccess(null);
  177.65 -        }
  177.66 -    }
  177.67 -    
  177.68 -    void onMessage(Object ev, String data) {
  177.69 -        Object json;
  177.70 -        try {
  177.71 -            data = data.trim();
  177.72 -            
  177.73 -            JSONTokener tok = new JSONTokener(data);
  177.74 -            Object obj;
  177.75 -            obj = data.startsWith("[") ? new JSONArray(tok) : new JSONObject(tok);
  177.76 -            json = LoadJSON.convertToArray(obj);
  177.77 -        } catch (JSONException ex) {
  177.78 -            json = data;
  177.79 -        }
  177.80 -        call.notifySuccess(json);
  177.81 -    }
  177.82 -    
  177.83 -    void onError(Object ev) {
  177.84 -        call.notifyError(new Exception(ev.toString()));
  177.85 -    }
  177.86 -
  177.87 -    void onClose(boolean wasClean, int code, String reason) {
  177.88 -        call.notifyError(null);
  177.89 -    }
  177.90 -    
  177.91 -    @JavaScriptBody(args = {}, body = "if (window.WebSocket) return true; else return false;")
  177.92 -    private static boolean isWebSocket() {
  177.93 -        return false;
  177.94 -    }
  177.95 -
  177.96 -    @JavaScriptBody(args = { "back", "url" }, javacall = true, body = ""
  177.97 -        + "if (window.WebSocket) {"
  177.98 -        + "  try {"
  177.99 -        + "    var ws = new window.WebSocket(url);"
 177.100 -        + "    ws.onopen = function(ev) { back.@org.apidesign.html.kofx.LoadWS::onOpen(Ljava/lang/Object;)(ev); };"
 177.101 -        + "    ws.onmessage = function(ev) { back.@org.apidesign.html.kofx.LoadWS::onMessage(Ljava/lang/Object;Ljava/lang/String;)(ev, ev.data); };"
 177.102 -        + "    ws.onerror = function(ev) { back.@org.apidesign.html.kofx.LoadWS::onError(Ljava/lang/Object;)(ev); };"
 177.103 -        + "    ws.onclose = function(ev) { back.@org.apidesign.html.kofx.LoadWS::onClose(ZILjava/lang/String;)(ev.wasClean, ev.code, ev.reason); };"
 177.104 -        + "    return ws;"
 177.105 -        + "  } catch (ex) {"
 177.106 -        + "    return null;"
 177.107 -        + "  }"
 177.108 -        + "} else {"
 177.109 -        + "  return null;"
 177.110 -        + "}"
 177.111 -    )
 177.112 -    private static Object initWebSocket(Object back, String url) {
 177.113 -        return null;
 177.114 -    }
 177.115 -    
 177.116 -
 177.117 -    @JavaScriptBody(args = { "ws", "msg" }, body = ""
 177.118 -        + "ws.send(msg);"
 177.119 -    )
 177.120 -    private void send(Object ws, String msg) {
 177.121 -    }
 177.122 -
 177.123 -    @JavaScriptBody(args = { "ws" }, body = "ws.close();")
 177.124 -    private static void close(Object ws) {
 177.125 -    }
 177.126 -
 177.127 -    void close() {
 177.128 -        close(ws);
 177.129 -    }
 177.130 -}
   178.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   178.2 +++ b/ko-fx/src/main/java/org/netbeans/html/kofx/Console.java	Mon Dec 16 17:16:40 2013 +0100
   178.3 @@ -0,0 +1,81 @@
   178.4 +/**
   178.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   178.6 + *
   178.7 + * Copyright 1997-2010 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.kofx;
  178.47 +
  178.48 +import java.util.logging.Level;
  178.49 +import java.util.logging.Logger;
  178.50 +import net.java.html.js.JavaScriptBody;
  178.51 +
  178.52 +/** This is an implementation package - just
  178.53 + * include its JAR on classpath and use official {@link Context} API
  178.54 + * to access the functionality.
  178.55 + * <p>
  178.56 + * Redirects JavaScript's messages to Java's {@link Logger}.
  178.57 + *
  178.58 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  178.59 + */
  178.60 +final class Console {
  178.61 +    private static final Logger LOG = Logger.getLogger(Console.class.getName());
  178.62 +    
  178.63 +    private Console() {
  178.64 +    }
  178.65 +
  178.66 +    static void register() {
  178.67 +        registerImpl("log", Level.INFO);
  178.68 +        registerImpl("info", Level.INFO);
  178.69 +        registerImpl("warn", Level.WARNING);
  178.70 +        registerImpl("error", Level.SEVERE);
  178.71 +    }
  178.72 +    
  178.73 +    @JavaScriptBody(args = { "attr", "l" }, 
  178.74 +        javacall = true, body = 
  178.75 +        "  window.console[attr] = function(m) {\n"
  178.76 +      + "    @org.netbeans.html.kofx.Console::log(Ljava/util/logging/Level;Ljava/lang/String;)(l, m);\n"
  178.77 +      + "  };\n"
  178.78 +    )
  178.79 +    private static native void registerImpl(String attr, Level l);
  178.80 +    
  178.81 +    static void log(Level l, String msg) {
  178.82 +        LOG.log(l, msg);
  178.83 +    }
  178.84 +}
   179.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   179.2 +++ b/ko-fx/src/main/java/org/netbeans/html/kofx/FXContext.java	Mon Dec 16 17:16:40 2013 +0100
   179.3 @@ -0,0 +1,222 @@
   179.4 +/**
   179.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   179.6 + *
   179.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   179.8 + *
   179.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  179.10 + * Other names may be trademarks of their respective owners.
  179.11 + *
  179.12 + * The contents of this file are subject to the terms of either the GNU
  179.13 + * General Public License Version 2 only ("GPL") or the Common
  179.14 + * Development and Distribution License("CDDL") (collectively, the
  179.15 + * "License"). You may not use this file except in compliance with the
  179.16 + * License. You can obtain a copy of the License at
  179.17 + * http://www.netbeans.org/cddl-gplv2.html
  179.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  179.19 + * specific language governing permissions and limitations under the
  179.20 + * License.  When distributing the software, include this License Header
  179.21 + * Notice in each file and include the License file at
  179.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  179.23 + * particular file as subject to the "Classpath" exception as provided
  179.24 + * by Oracle in the GPL Version 2 section of the License file that
  179.25 + * accompanied this code. If applicable, add the following below the
  179.26 + * License Header, with the fields enclosed by brackets [] replaced by
  179.27 + * your own identifying information:
  179.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  179.29 + *
  179.30 + * Contributor(s):
  179.31 + *
  179.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  179.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  179.34 + *
  179.35 + * If you wish your version of this file to be governed by only the CDDL
  179.36 + * or only the GPL Version 2, indicate your decision by adding
  179.37 + * "[Contributor] elects to include this software in this distribution
  179.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  179.39 + * single choice of license, a recipient has the option to distribute
  179.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  179.41 + * to extend the choice of license to its licensees as provided above.
  179.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  179.43 + * Version 2 license, then the option applies only if the new code is
  179.44 + * made subject to such option by the copyright holder.
  179.45 + */
  179.46 +package org.netbeans.html.kofx;
  179.47 +
  179.48 +import java.io.Closeable;
  179.49 +import java.io.IOException;
  179.50 +import java.io.InputStream;
  179.51 +import java.util.ServiceLoader;
  179.52 +import java.util.logging.Logger;
  179.53 +import javafx.application.Platform;
  179.54 +import net.java.html.js.JavaScriptBody;
  179.55 +import netscape.javascript.JSObject;
  179.56 +import org.apidesign.html.boot.spi.Fn;
  179.57 +import org.apidesign.html.context.spi.Contexts;
  179.58 +import org.apidesign.html.json.spi.FunctionBinding;
  179.59 +import org.apidesign.html.json.spi.JSONCall;
  179.60 +import org.apidesign.html.json.spi.PropertyBinding;
  179.61 +import org.apidesign.html.json.spi.Technology;
  179.62 +import org.apidesign.html.json.spi.Transfer;
  179.63 +import org.apidesign.html.json.spi.WSTransfer;
  179.64 +import org.openide.util.lookup.ServiceProvider;
  179.65 +
  179.66 +/** This is an implementation package - just
  179.67 + * include its JAR on classpath and use official {@link Context} API
  179.68 + * to access the functionality.
  179.69 + * <p>
  179.70 + * Registers {@link ContextProvider}, so {@link ServiceLoader} can find it.
  179.71 + *
  179.72 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  179.73 + */
  179.74 +public final class FXContext
  179.75 +implements Technology.BatchInit<JSObject>, Transfer, WSTransfer<LoadWS> {
  179.76 +    static final Logger LOG = Logger.getLogger(FXContext.class.getName());
  179.77 +    private static Boolean javaScriptEnabled;
  179.78 +    private final Fn.Presenter browserContext;
  179.79 +
  179.80 +    public FXContext(Fn.Presenter browserContext) {
  179.81 +        this.browserContext = browserContext;
  179.82 +    }
  179.83 +    
  179.84 +    @JavaScriptBody(args = {}, body = "return true;")
  179.85 +    private static boolean isJavaScriptEnabledJs() {
  179.86 +        return false;
  179.87 +    }
  179.88 +    
  179.89 +    static boolean isJavaScriptEnabled() {
  179.90 +        if (javaScriptEnabled != null) {
  179.91 +            return javaScriptEnabled;
  179.92 +        }
  179.93 +        return javaScriptEnabled = isJavaScriptEnabledJs();
  179.94 +    }
  179.95 +
  179.96 +    final boolean areWebSocketsSupported() {
  179.97 +        return LoadWS.isSupported();
  179.98 +    }
  179.99 +
 179.100 +
 179.101 +    @Override
 179.102 +    public JSObject wrapModel(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
 179.103 +        String[] propNames = new String[propArr.length];
 179.104 +        boolean[] propReadOnly = new boolean[propArr.length];
 179.105 +        Object[] propValues = new Object[propArr.length];
 179.106 +        for (int i = 0; i < propNames.length; i++) {
 179.107 +            propNames[i] = propArr[i].getPropertyName();
 179.108 +            propReadOnly[i] = propArr[i].isReadOnly();
 179.109 +            propValues[i] = propArr[i].getValue();
 179.110 +        }
 179.111 +        String[] funcNames = new String[funcArr.length];
 179.112 +        for (int i = 0; i < funcNames.length; i++) {
 179.113 +            funcNames[i] = funcArr[i].getFunctionName();
 179.114 +        }
 179.115 +        
 179.116 +        return Knockout.wrapModel(model, 
 179.117 +            propNames, propReadOnly, Knockout.toArray(propValues), propArr, 
 179.118 +            funcNames, funcArr
 179.119 +        );
 179.120 +    }
 179.121 +    
 179.122 +    @Override
 179.123 +    public JSObject wrapModel(Object model) {
 179.124 +        throw new UnsupportedOperationException();
 179.125 +    }
 179.126 +
 179.127 +    @Override
 179.128 +    public void bind(PropertyBinding b, Object model, JSObject data) {
 179.129 +        throw new UnsupportedOperationException();
 179.130 +    }
 179.131 +
 179.132 +    @Override
 179.133 +    public void valueHasMutated(JSObject data, String propertyName) {
 179.134 +        Knockout.valueHasMutated(data, propertyName);
 179.135 +    }
 179.136 +
 179.137 +    @Override
 179.138 +    public void expose(FunctionBinding fb, Object model, JSObject d) {
 179.139 +        throw new UnsupportedOperationException();
 179.140 +    }
 179.141 +
 179.142 +    @Override
 179.143 +    public void applyBindings(JSObject data) {
 179.144 +        Knockout.applyBindings(data);
 179.145 +    }
 179.146 +
 179.147 +    @Override
 179.148 +    public Object wrapArray(Object[] arr) {
 179.149 +        return Knockout.toArray(arr);
 179.150 +    }
 179.151 +
 179.152 +    @Override
 179.153 +    public void extract(Object obj, String[] props, Object[] values) {
 179.154 +        LoadJSON.extractJSON(obj, props, values);
 179.155 +    }
 179.156 +
 179.157 +    @Override
 179.158 +    public void loadJSON(final JSONCall call) {
 179.159 +        LoadJSON.loadJSON(call);
 179.160 +    }
 179.161 +
 179.162 +    @Override
 179.163 +    public <M> M toModel(Class<M> modelClass, Object data) {
 179.164 +        if (data instanceof JSObject) {
 179.165 +            data = ((JSObject)data).getMember("ko-fx.model"); // NOI18N
 179.166 +        }
 179.167 +        return modelClass.cast(data);
 179.168 +    }
 179.169 +
 179.170 +    @Override
 179.171 +    public Object toJSON(InputStream is) throws IOException {
 179.172 +        return LoadJSON.parse(is);
 179.173 +    }
 179.174 +
 179.175 +    @Override
 179.176 +    public void runSafe(final Runnable r) {
 179.177 +        class Wrap implements Runnable {
 179.178 +            @Override public void run() {
 179.179 +                try (Closeable c = Fn.activate(browserContext)) {
 179.180 +                    r.run();
 179.181 +                } catch (IOException ex) {
 179.182 +                    // cannot be thrown
 179.183 +                }
 179.184 +            }
 179.185 +        }
 179.186 +        Wrap w = new Wrap();
 179.187 +        
 179.188 +        if (Platform.isFxApplicationThread()) {
 179.189 +            w.run();
 179.190 +        } else {
 179.191 +            Platform.runLater(w);
 179.192 +        }
 179.193 +    }
 179.194 +
 179.195 +    @Override
 179.196 +    public LoadWS open(String url, JSONCall onReply) {
 179.197 +        return new LoadWS(onReply, url);
 179.198 +    }
 179.199 +
 179.200 +    @Override
 179.201 +    public void send(LoadWS socket, JSONCall data) {
 179.202 +        socket.send(data);
 179.203 +    }
 179.204 +
 179.205 +    @Override
 179.206 +    public void close(LoadWS socket) {
 179.207 +        socket.close();
 179.208 +    }
 179.209 +    
 179.210 +    @ServiceProvider(service = Contexts.Provider.class)
 179.211 +    public static final class Prvdr implements Contexts.Provider {
 179.212 +        @Override
 179.213 +        public void fillContext(Contexts.Builder context, Class<?> requestor) {
 179.214 +            if (isJavaScriptEnabled()) {
 179.215 +                FXContext c = new FXContext(Fn.activePresenter());
 179.216 +                
 179.217 +                context.register(Technology.class, c, 100);
 179.218 +                context.register(Transfer.class, c, 100);
 179.219 +                if (c.areWebSocketsSupported()) {
 179.220 +                    context.register(WSTransfer.class, c, 100);
 179.221 +                }
 179.222 +            }
 179.223 +        }
 179.224 +    }
 179.225 +}
   180.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   180.2 +++ b/ko-fx/src/main/java/org/netbeans/html/kofx/Knockout.java	Mon Dec 16 17:16:40 2013 +0100
   180.3 @@ -0,0 +1,145 @@
   180.4 +/**
   180.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   180.6 + *
   180.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   180.8 + *
   180.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  180.10 + * Other names may be trademarks of their respective owners.
  180.11 + *
  180.12 + * The contents of this file are subject to the terms of either the GNU
  180.13 + * General Public License Version 2 only ("GPL") or the Common
  180.14 + * Development and Distribution License("CDDL") (collectively, the
  180.15 + * "License"). You may not use this file except in compliance with the
  180.16 + * License. You can obtain a copy of the License at
  180.17 + * http://www.netbeans.org/cddl-gplv2.html
  180.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  180.19 + * specific language governing permissions and limitations under the
  180.20 + * License.  When distributing the software, include this License Header
  180.21 + * Notice in each file and include the License file at
  180.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  180.23 + * particular file as subject to the "Classpath" exception as provided
  180.24 + * by Oracle in the GPL Version 2 section of the License file that
  180.25 + * accompanied this code. If applicable, add the following below the
  180.26 + * License Header, with the fields enclosed by brackets [] replaced by
  180.27 + * your own identifying information:
  180.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  180.29 + *
  180.30 + * Contributor(s):
  180.31 + *
  180.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  180.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  180.34 + *
  180.35 + * If you wish your version of this file to be governed by only the CDDL
  180.36 + * or only the GPL Version 2, indicate your decision by adding
  180.37 + * "[Contributor] elects to include this software in this distribution
  180.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  180.39 + * single choice of license, a recipient has the option to distribute
  180.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  180.41 + * to extend the choice of license to its licensees as provided above.
  180.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  180.43 + * Version 2 license, then the option applies only if the new code is
  180.44 + * made subject to such option by the copyright holder.
  180.45 + */
  180.46 +package org.netbeans.html.kofx;
  180.47 +
  180.48 +import net.java.html.js.JavaScriptBody;
  180.49 +import net.java.html.js.JavaScriptResource;
  180.50 +import net.java.html.json.Model;
  180.51 +import netscape.javascript.JSObject;
  180.52 +import org.apidesign.html.json.spi.FunctionBinding;
  180.53 +import org.apidesign.html.json.spi.PropertyBinding;
  180.54 +
  180.55 +/** This is an implementation package - just
  180.56 + * include its JAR on classpath and use official {@link Context} API
  180.57 + * to access the functionality.
  180.58 + * <p>
  180.59 + * Provides binding between {@link Model models} and knockout.js running
  180.60 + * inside a JavaFX WebView. 
  180.61 + *
  180.62 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  180.63 + */
  180.64 +@JavaScriptResource("knockout-2.2.1.js")
  180.65 +final class Knockout {
  180.66 +    static final JSObject KObject;
  180.67 +    static {
  180.68 +        Console.register();
  180.69 +        KObject = (JSObject) kObj();
  180.70 +    }
  180.71 +
  180.72 +    static Object toArray(Object[] arr) {
  180.73 +        return KObject.call("array", arr);
  180.74 +    }
  180.75 +    
  180.76 +    @JavaScriptBody(args = { "model", "prop" }, body =
  180.77 +          "if (model) {\n"
  180.78 +        + "  var koProp = model[prop];\n"
  180.79 +        + "  if (koProp && koProp['valueHasMutated']) {\n"
  180.80 +        + "    koProp['valueHasMutated']();\n"
  180.81 +        + "  }\n"
  180.82 +        + "}\n"
  180.83 +    )
  180.84 +    public native static void valueHasMutated(JSObject model, String prop);
  180.85 +
  180.86 +    @JavaScriptBody(args = { "bindings" }, body = "ko.applyBindings(bindings);")
  180.87 +    native static void applyBindings(Object bindings);
  180.88 +    
  180.89 +    @JavaScriptBody(args = {}, body =
  180.90 +              "  var k = {};"
  180.91 +            + "  k.array= function() {"
  180.92 +            + "    return Array.prototype.slice.call(arguments);"
  180.93 +            + "  };"
  180.94 +            + "  return k;"
  180.95 +    )
  180.96 +    private static native Object kObj();
  180.97 +        
  180.98 +        
  180.99 +    @JavaScriptBody(
 180.100 +        javacall = true,
 180.101 +        args = {"model", "propNames", "propReadOnly", "propValues", "propArr", "funcNames", "funcArr"},
 180.102 +        body
 180.103 +        = "var ret = {};\n"
 180.104 +        + "ret['ko-fx.model'] = model;\n"
 180.105 +        + "function koComputed(name, readOnly, value, prop) {\n"
 180.106 +        + "  function realGetter() {\n"
 180.107 +        + "    try {"
 180.108 +        + "      var v = prop.@org.apidesign.html.json.spi.PropertyBinding::getValue()();"
 180.109 +        + "      return v;"
 180.110 +        + "    } catch (e) {"
 180.111 +        + "      alert(\"Cannot call getValue on \" + model + \" prop: \" + name + \" error: \" + e);"
 180.112 +        + "    }"
 180.113 +        + "  }\n"
 180.114 +        + "  var activeGetter = function() { return value; };\n"
 180.115 +        + "  var bnd = {"
 180.116 +        + "    read: function() {"
 180.117 +        + "      var r = activeGetter();"
 180.118 +        + "      activeGetter = realGetter;"
 180.119 +        + "      return r;"
 180.120 +        + "    },"
 180.121 +        + "    owner: ret\n"
 180.122 +        + "  };\n"
 180.123 +        + "  if (!readOnly) {\n"
 180.124 +        + "    bnd.write = function(val) {\n"
 180.125 +        + "      prop.@org.apidesign.html.json.spi.PropertyBinding::setValue(Ljava/lang/Object;)(val);\n"
 180.126 +        + "    };"
 180.127 +        + "  };"
 180.128 +        + "  ret[name] = ko.computed(bnd);"
 180.129 +        + "}\n"
 180.130 +        + "for (var i = 0; i < propNames.length; i++) {\n"
 180.131 +        + "  koComputed(propNames[i], propReadOnly[i], propValues[i], propArr[i]);\n"
 180.132 +        + "}\n"
 180.133 +        + "function koExpose(name, func) {\n"
 180.134 +        + "  ret[name] = function(data, ev) {\n"
 180.135 +        + "    func.@org.apidesign.html.json.spi.FunctionBinding::call(Ljava/lang/Object;Ljava/lang/Object;)(data, ev);\n"
 180.136 +        + "  };\n"
 180.137 +        + "}\n"
 180.138 +        + "for (var i = 0; i < funcNames.length; i++) {\n"
 180.139 +        + "  koExpose(funcNames[i], funcArr[i]);\n"
 180.140 +        + "}\n"
 180.141 +        + "return ret;\n"
 180.142 +        )
 180.143 +    static native JSObject wrapModel(
 180.144 +        Object model,
 180.145 +        String[] propNames, boolean[] propReadOnly, Object propValues, PropertyBinding[] propArr,
 180.146 +        String[] funcNames, FunctionBinding[] funcArr
 180.147 +    );
 180.148 +}
   181.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   181.2 +++ b/ko-fx/src/main/java/org/netbeans/html/kofx/LoadJSON.java	Mon Dec 16 17:16:40 2013 +0100
   181.3 @@ -0,0 +1,267 @@
   181.4 +/**
   181.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   181.6 + *
   181.7 + * Copyright 1997-2010 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.kofx;
  181.47 +
  181.48 +import java.io.IOException;
  181.49 +import java.io.InputStream;
  181.50 +import java.io.InputStreamReader;
  181.51 +import java.io.OutputStream;
  181.52 +import java.io.PushbackInputStream;
  181.53 +import java.io.Reader;
  181.54 +import java.net.HttpURLConnection;
  181.55 +import java.net.MalformedURLException;
  181.56 +import java.net.URL;
  181.57 +import java.net.URLConnection;
  181.58 +import java.util.Iterator;
  181.59 +import java.util.concurrent.Executor;
  181.60 +import java.util.concurrent.Executors;
  181.61 +import java.util.concurrent.ThreadFactory;
  181.62 +import java.util.logging.Level;
  181.63 +import java.util.logging.Logger;
  181.64 +import javafx.application.Platform;
  181.65 +import net.java.html.js.JavaScriptBody;
  181.66 +import netscape.javascript.JSObject;
  181.67 +import org.apidesign.html.json.spi.JSONCall;
  181.68 +import org.json.JSONArray;
  181.69 +import org.json.JSONException;
  181.70 +import org.json.JSONObject;
  181.71 +import org.json.JSONTokener;
  181.72 +
  181.73 +/** This is an implementation package - just
  181.74 + * include its JAR on classpath and use official {@link Context} API
  181.75 + * to access the functionality.
  181.76 + *
  181.77 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  181.78 + */
  181.79 +final class LoadJSON implements Runnable {
  181.80 +    private static final Logger LOG = FXContext.LOG;
  181.81 +    private static final Executor REQ = Executors.newCachedThreadPool(new ThreadFactory() {
  181.82 +        @Override
  181.83 +        public Thread newThread(Runnable runnable) {
  181.84 +            Thread thread = Executors.defaultThreadFactory().newThread(runnable);
  181.85 +            thread.setDaemon(true);
  181.86 +            return thread;
  181.87 +        }
  181.88 +    });
  181.89 +
  181.90 +    private final JSONCall call;
  181.91 +    private final URL base;
  181.92 +    private Throwable error;
  181.93 +    private Object json;
  181.94 +
  181.95 +
  181.96 +    private LoadJSON(JSONCall call) {
  181.97 +        this.call = call;
  181.98 +        URL b;
  181.99 +        try {
 181.100 +            b = new URL(findBaseURL());
 181.101 +        } catch (MalformedURLException ex) {
 181.102 +            LOG.log(Level.SEVERE, "Can't find base url for " + call.composeURL("dummy"), ex);
 181.103 +            b = null;
 181.104 +        }
 181.105 +        this.base = b;
 181.106 +    }
 181.107 +
 181.108 +    public static void loadJSON(JSONCall call) {
 181.109 +        assert !"WebSocket".equals(call.getMethod());
 181.110 +        REQ.execute(new LoadJSON((call)));
 181.111 +    }
 181.112 +
 181.113 +    @Override
 181.114 +    public void run() {
 181.115 +        if (Platform.isFxApplicationThread()) {
 181.116 +            if (error != null) {
 181.117 +                call.notifyError(error);
 181.118 +            } else {
 181.119 +                call.notifySuccess(json);
 181.120 +            }
 181.121 +            return;
 181.122 +        }
 181.123 +        final String url;
 181.124 +        if (call.isJSONP()) {
 181.125 +            url = call.composeURL("dummy");
 181.126 +        } else {
 181.127 +            url = call.composeURL(null);
 181.128 +        }
 181.129 +        try {
 181.130 +            final URL u = new URL(base, url.replace(" ", "%20"));
 181.131 +            URLConnection conn = u.openConnection();
 181.132 +            if (conn instanceof HttpURLConnection) {
 181.133 +                HttpURLConnection huc = (HttpURLConnection) conn;
 181.134 +                if (call.getMethod() != null) {
 181.135 +                    huc.setRequestMethod(call.getMethod());
 181.136 +                }
 181.137 +                if (call.isDoOutput()) {
 181.138 +                    huc.setDoOutput(true);
 181.139 +                    final OutputStream os = huc.getOutputStream();
 181.140 +                    call.writeData(os);
 181.141 +                    os.flush();
 181.142 +                }
 181.143 +            }
 181.144 +            final PushbackInputStream is = new PushbackInputStream(
 181.145 +                conn.getInputStream(), 1
 181.146 +            );
 181.147 +            boolean array = false;
 181.148 +            boolean string = false;
 181.149 +            if (call.isJSONP()) {
 181.150 +                for (;;) {
 181.151 +                    int ch = is.read();
 181.152 +                    if (ch == -1) {
 181.153 +                        break;
 181.154 +                    }
 181.155 +                    if (ch == '[') {
 181.156 +                        is.unread(ch);
 181.157 +                        array = true;
 181.158 +                        break;
 181.159 +                    }
 181.160 +                    if (ch == '{') {
 181.161 +                        is.unread(ch);
 181.162 +                        break;
 181.163 +                    }
 181.164 +                }
 181.165 +            } else {
 181.166 +                int ch = is.read();
 181.167 +                if (ch == -1) {
 181.168 +                    string = true;
 181.169 +                } else {
 181.170 +                    array = ch == '[';
 181.171 +                    is.unread(ch);
 181.172 +                    if (!array && ch != '{') {
 181.173 +                        string = true;
 181.174 +                    }
 181.175 +                }
 181.176 +            }
 181.177 +            try {
 181.178 +                if (string) {
 181.179 +                    throw new JSONException("");
 181.180 +                }
 181.181 +                Reader r = new InputStreamReader(is, "UTF-8");
 181.182 +
 181.183 +                JSONTokener tok = new JSONTokener(r);
 181.184 +                Object obj;
 181.185 +                obj = array ? new JSONArray(tok) : new JSONObject(tok);
 181.186 +                json = convertToArray(obj);
 181.187 +            } catch (JSONException ex) {
 181.188 +                Reader r = new InputStreamReader(is, "UTF-8");
 181.189 +                StringBuilder sb = new StringBuilder();
 181.190 +                for (;;) {
 181.191 +                    int ch = r.read();
 181.192 +                    if (ch == -1) {
 181.193 +                        break;
 181.194 +                    }
 181.195 +                    sb.append((char)ch);
 181.196 +                }
 181.197 +                json = sb.toString();
 181.198 +            }
 181.199 +        } catch (IOException ex) {
 181.200 +            error = ex;
 181.201 +        } finally {
 181.202 +            Platform.runLater(this);
 181.203 +        }
 181.204 +    }
 181.205 +
 181.206 +    static Object convertToArray(Object o) throws JSONException {
 181.207 +        if (o instanceof JSONArray) {
 181.208 +            JSONArray ja = (JSONArray)o;
 181.209 +            Object[] arr = new Object[ja.length()];
 181.210 +            for (int i = 0; i < arr.length; i++) {
 181.211 +                arr[i] = convertToArray(ja.get(i));
 181.212 +            }
 181.213 +            return arr;
 181.214 +        } else if (o instanceof JSONObject) {
 181.215 +            JSONObject obj = (JSONObject)o;
 181.216 +            Iterator it = obj.keys();
 181.217 +            while (it.hasNext()) {
 181.218 +                String key = (String)it.next();
 181.219 +                obj.put(key, convertToArray(obj.get(key)));
 181.220 +            }
 181.221 +            return obj;
 181.222 +        } else {
 181.223 +            return o;
 181.224 +        }
 181.225 +    }
 181.226 +    
 181.227 +    public static void extractJSON(Object jsonObject, String[] props, Object[] values) {
 181.228 +        if (jsonObject instanceof JSONObject) {
 181.229 +            JSONObject obj = (JSONObject)jsonObject;
 181.230 +            for (int i = 0; i < props.length; i++) {
 181.231 +                try {
 181.232 +                    values[i] = obj.has(props[i]) ? obj.get(props[i]) : null;
 181.233 +                } catch (JSONException ex) {
 181.234 +                    LoadJSON.LOG.log(Level.SEVERE, "Can't read " + props[i] + " from " + jsonObject, ex);
 181.235 +                }
 181.236 +            }
 181.237 +        }
 181.238 +        if (jsonObject instanceof JSObject) {
 181.239 +            JSObject obj = (JSObject)jsonObject;
 181.240 +            for (int i = 0; i < props.length; i++) {
 181.241 +                Object val = obj.getMember(props[i]);
 181.242 +                values[i] = isDefined(val) ? val : null;
 181.243 +            }
 181.244 +        }
 181.245 +    }
 181.246 +    
 181.247 +    public static Object parse(InputStream is) throws IOException {
 181.248 +        try {
 181.249 +            InputStreamReader r = new InputStreamReader(is, "UTF-8");
 181.250 +            JSONTokener t = new JSONTokener(r);
 181.251 +            return new JSONObject(t);
 181.252 +        } catch (JSONException ex) {
 181.253 +            throw new IOException(ex);
 181.254 +        }
 181.255 +    }
 181.256 +
 181.257 +    @JavaScriptBody(args = {  }, body = 
 181.258 +          "var h;"
 181.259 +        + "if (!!window && !!window.location && !!window.location.href)\n"
 181.260 +        + "  h = window.location.href;\n"
 181.261 +        + "else "
 181.262 +        + "  h = null;"
 181.263 +        + "return h;\n"
 181.264 +    )
 181.265 +    private static native String findBaseURL();
 181.266 +    
 181.267 +    private static boolean isDefined(Object val) {
 181.268 +        return !"undefined".equals(val);
 181.269 +    }
 181.270 +}
   182.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   182.2 +++ b/ko-fx/src/main/java/org/netbeans/html/kofx/LoadWS.java	Mon Dec 16 17:16:40 2013 +0100
   182.3 @@ -0,0 +1,149 @@
   182.4 +/**
   182.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   182.6 + *
   182.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   182.8 + *
   182.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  182.10 + * Other names may be trademarks of their respective owners.
  182.11 + *
  182.12 + * The contents of this file are subject to the terms of either the GNU
  182.13 + * General Public License Version 2 only ("GPL") or the Common
  182.14 + * Development and Distribution License("CDDL") (collectively, the
  182.15 + * "License"). You may not use this file except in compliance with the
  182.16 + * License. You can obtain a copy of the License at
  182.17 + * http://www.netbeans.org/cddl-gplv2.html
  182.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  182.19 + * specific language governing permissions and limitations under the
  182.20 + * License.  When distributing the software, include this License Header
  182.21 + * Notice in each file and include the License file at
  182.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  182.23 + * particular file as subject to the "Classpath" exception as provided
  182.24 + * by Oracle in the GPL Version 2 section of the License file that
  182.25 + * accompanied this code. If applicable, add the following below the
  182.26 + * License Header, with the fields enclosed by brackets [] replaced by
  182.27 + * your own identifying information:
  182.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  182.29 + *
  182.30 + * Contributor(s):
  182.31 + *
  182.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  182.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  182.34 + *
  182.35 + * If you wish your version of this file to be governed by only the CDDL
  182.36 + * or only the GPL Version 2, indicate your decision by adding
  182.37 + * "[Contributor] elects to include this software in this distribution
  182.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  182.39 + * single choice of license, a recipient has the option to distribute
  182.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  182.41 + * to extend the choice of license to its licensees as provided above.
  182.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  182.43 + * Version 2 license, then the option applies only if the new code is
  182.44 + * made subject to such option by the copyright holder.
  182.45 + */
  182.46 +package org.netbeans.html.kofx;
  182.47 +
  182.48 +import net.java.html.js.JavaScriptBody;
  182.49 +import org.apidesign.html.json.spi.JSONCall;
  182.50 +import org.json.JSONArray;
  182.51 +import org.json.JSONException;
  182.52 +import org.json.JSONObject;
  182.53 +import org.json.JSONTokener;
  182.54 +
  182.55 +/** Communication with WebSockets for WebView 1.8.
  182.56 + *
  182.57 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  182.58 + */
  182.59 +final class LoadWS {
  182.60 +    private static final boolean SUPPORTED = isWebSocket();
  182.61 +    private final Object ws;
  182.62 +    private final JSONCall call;
  182.63 +
  182.64 +    LoadWS(JSONCall first, String url) {
  182.65 +        call = first;
  182.66 +        ws = initWebSocket(this, url);
  182.67 +        if (ws == null) {
  182.68 +            first.notifyError(new IllegalArgumentException("Wrong URL: " + url));
  182.69 +        }
  182.70 +    }
  182.71 +    
  182.72 +    static boolean isSupported() {
  182.73 +        return SUPPORTED;
  182.74 +    }
  182.75 +    
  182.76 +    void send(JSONCall call) {
  182.77 +        push(call);
  182.78 +    }
  182.79 +    
  182.80 +    private synchronized void push(JSONCall call) {
  182.81 +        send(ws, call.getMessage());
  182.82 +    }
  182.83 +
  182.84 +    void onOpen(Object ev) {
  182.85 +        if (!call.isDoOutput()) {
  182.86 +            call.notifySuccess(null);
  182.87 +        }
  182.88 +    }
  182.89 +    
  182.90 +    void onMessage(Object ev, String data) {
  182.91 +        Object json;
  182.92 +        try {
  182.93 +            data = data.trim();
  182.94 +            
  182.95 +            JSONTokener tok = new JSONTokener(data);
  182.96 +            Object obj;
  182.97 +            obj = data.startsWith("[") ? new JSONArray(tok) : new JSONObject(tok);
  182.98 +            json = LoadJSON.convertToArray(obj);
  182.99 +        } catch (JSONException ex) {
 182.100 +            json = data;
 182.101 +        }
 182.102 +        call.notifySuccess(json);
 182.103 +    }
 182.104 +    
 182.105 +    void onError(Object ev) {
 182.106 +        call.notifyError(new Exception(ev.toString()));
 182.107 +    }
 182.108 +
 182.109 +    void onClose(boolean wasClean, int code, String reason) {
 182.110 +        call.notifyError(null);
 182.111 +    }
 182.112 +    
 182.113 +    @JavaScriptBody(args = {}, body = "if (window.WebSocket) return true; else return false;")
 182.114 +    private static boolean isWebSocket() {
 182.115 +        return false;
 182.116 +    }
 182.117 +
 182.118 +    @JavaScriptBody(args = { "back", "url" }, javacall = true, body = ""
 182.119 +        + "if (window.WebSocket) {"
 182.120 +        + "  try {"
 182.121 +        + "    var ws = new window.WebSocket(url);"
 182.122 +        + "    ws.onopen = function(ev) { back.@org.netbeans.html.kofx.LoadWS::onOpen(Ljava/lang/Object;)(ev); };"
 182.123 +        + "    ws.onmessage = function(ev) { back.@org.netbeans.html.kofx.LoadWS::onMessage(Ljava/lang/Object;Ljava/lang/String;)(ev, ev.data); };"
 182.124 +        + "    ws.onerror = function(ev) { back.@org.netbeans.html.kofx.LoadWS::onError(Ljava/lang/Object;)(ev); };"
 182.125 +        + "    ws.onclose = function(ev) { back.@org.netbeans.html.kofx.LoadWS::onClose(ZILjava/lang/String;)(ev.wasClean, ev.code, ev.reason); };"
 182.126 +        + "    return ws;"
 182.127 +        + "  } catch (ex) {"
 182.128 +        + "    return null;"
 182.129 +        + "  }"
 182.130 +        + "} else {"
 182.131 +        + "  return null;"
 182.132 +        + "}"
 182.133 +    )
 182.134 +    private static Object initWebSocket(Object back, String url) {
 182.135 +        return null;
 182.136 +    }
 182.137 +    
 182.138 +
 182.139 +    @JavaScriptBody(args = { "ws", "msg" }, body = ""
 182.140 +        + "ws.send(msg);"
 182.141 +    )
 182.142 +    private void send(Object ws, String msg) {
 182.143 +    }
 182.144 +
 182.145 +    @JavaScriptBody(args = { "ws" }, body = "ws.close();")
 182.146 +    private static void close(Object ws) {
 182.147 +    }
 182.148 +
 182.149 +    void close() {
 182.150 +        close(ws);
 182.151 +    }
 182.152 +}
   183.1 --- a/ko-fx/src/main/resources/org/apidesign/html/kofx/knockout-2.2.1.js	Mon Dec 16 17:16:02 2013 +0100
   183.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   183.3 @@ -1,3594 +0,0 @@
   183.4 -// Knockout JavaScript library v2.2.1
   183.5 -// (c) Steven Sanderson - http://knockoutjs.com/
   183.6 -// License: MIT (http://www.opensource.org/licenses/mit-license.php)
   183.7 -
   183.8 -(function(){
   183.9 -var DEBUG=true;
  183.10 -(function(window,document,navigator,jQuery,undefined){
  183.11 -!function(factory) {
  183.12 -    // Support three module loading scenarios
  183.13 -    if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
  183.14 -        // [1] CommonJS/Node.js
  183.15 -        var target = module['exports'] || exports; // module.exports is for Node.js
  183.16 -        factory(target);
  183.17 -    } else if (typeof define === 'function' && define['amd']) {
  183.18 -        // [2] AMD anonymous module
  183.19 -        define(['exports'], factory);
  183.20 -    } else {
  183.21 -        // [3] No module loader (plain <script> tag) - put directly in global namespace
  183.22 -        factory(window['ko'] = {});
  183.23 -    }
  183.24 -}(function(koExports){
  183.25 -// Internally, all KO objects are attached to koExports (even the non-exported ones whose names will be minified by the closure compiler).
  183.26 -// In the future, the following "ko" variable may be made distinct from "koExports" so that private objects are not externally reachable.
  183.27 -var ko = typeof koExports !== 'undefined' ? koExports : {};
  183.28 -// Google Closure Compiler helpers (used only to make the minified file smaller)
  183.29 -ko.exportSymbol = function(koPath, object) {
  183.30 -	var tokens = koPath.split(".");
  183.31 -
  183.32 -	// In the future, "ko" may become distinct from "koExports" (so that non-exported objects are not reachable)
  183.33 -	// At that point, "target" would be set to: (typeof koExports !== "undefined" ? koExports : ko)
  183.34 -	var target = ko;
  183.35 -
  183.36 -	for (var i = 0; i < tokens.length - 1; i++)
  183.37 -		target = target[tokens[i]];
  183.38 -	target[tokens[tokens.length - 1]] = object;
  183.39 -};
  183.40 -ko.exportProperty = function(owner, publicName, object) {
  183.41 -  owner[publicName] = object;
  183.42 -};
  183.43 -ko.version = "2.2.1";
  183.44 -
  183.45 -ko.exportSymbol('version', ko.version);
  183.46 -ko.utils = new (function () {
  183.47 -    var stringTrimRegex = /^(\s|\u00A0)+|(\s|\u00A0)+$/g;
  183.48 -
  183.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)
  183.50 -    var knownEvents = {}, knownEventTypesByEventName = {};
  183.51 -    var keyEventTypeName = /Firefox\/2/i.test(navigator.userAgent) ? 'KeyboardEvent' : 'UIEvents';
  183.52 -    knownEvents[keyEventTypeName] = ['keyup', 'keydown', 'keypress'];
  183.53 -    knownEvents['MouseEvents'] = ['click', 'dblclick', 'mousedown', 'mouseup', 'mousemove', 'mouseover', 'mouseout', 'mouseenter', 'mouseleave'];
  183.54 -    for (var eventType in knownEvents) {
  183.55 -        var knownEventsForType = knownEvents[eventType];
  183.56 -        if (knownEventsForType.length) {
  183.57 -            for (var i = 0, j = knownEventsForType.length; i < j; i++)
  183.58 -                knownEventTypesByEventName[knownEventsForType[i]] = eventType;
  183.59 -        }
  183.60 -    }
  183.61 -    var eventsThatMustBeRegisteredUsingAttachEvent = { 'propertychange': true }; // Workaround for an IE9 issue - https://github.com/SteveSanderson/knockout/issues/406
  183.62 -
  183.63 -    // Detect IE versions for bug workarounds (uses IE conditionals, not UA string, for robustness)
  183.64 -    // Note that, since IE 10 does not support conditional comments, the following logic only detects IE < 10.
  183.65 -    // Currently this is by design, since IE 10+ behaves correctly when treated as a standard browser.
  183.66 -    // If there is a future need to detect specific versions of IE10+, we will amend this.
  183.67 -    var ieVersion = (function() {
  183.68 -        var version = 3, div = document.createElement('div'), iElems = div.getElementsByTagName('i');
  183.69 -
  183.70 -        // Keep constructing conditional HTML blocks until we hit one that resolves to an empty fragment
  183.71 -        while (
  183.72 -            div.innerHTML = '<!--[if gt IE ' + (++version) + ']><i></i><![endif]-->',
  183.73 -            iElems[0]
  183.74 -        );
  183.75 -        return version > 4 ? version : undefined;
  183.76 -    }());
  183.77 -    var isIe6 = ieVersion === 6,
  183.78 -        isIe7 = ieVersion === 7;
  183.79 -
  183.80 -    function isClickOnCheckableElement(element, eventType) {
  183.81 -        if ((ko.utils.tagNameLower(element) !== "input") || !element.type) return false;
  183.82 -        if (eventType.toLowerCase() != "click") return false;
  183.83 -        var inputType = element.type;
  183.84 -        return (inputType == "checkbox") || (inputType == "radio");
  183.85 -    }
  183.86 -
  183.87 -    return {
  183.88 -        fieldsIncludedWithJsonPost: ['authenticity_token', /^__RequestVerificationToken(_.*)?$/],
  183.89 -
  183.90 -        arrayForEach: function (array, action) {
  183.91 -            for (var i = 0, j = array.length; i < j; i++)
  183.92 -                action(array[i]);
  183.93 -        },
  183.94 -
  183.95 -        arrayIndexOf: function (array, item) {
  183.96 -            if (typeof Array.prototype.indexOf == "function")
  183.97 -                return Array.prototype.indexOf.call(array, item);
  183.98 -            for (var i = 0, j = array.length; i < j; i++)
  183.99 -                if (array[i] === item)
 183.100 -                    return i;
 183.101 -            return -1;
 183.102 -        },
 183.103 -
 183.104 -        arrayFirst: function (array, predicate, predicateOwner) {
 183.105 -            for (var i = 0, j = array.length; i < j; i++)
 183.106 -                if (predicate.call(predicateOwner, array[i]))
 183.107 -                    return array[i];
 183.108 -            return null;
 183.109 -        },
 183.110 -
 183.111 -        arrayRemoveItem: function (array, itemToRemove) {
 183.112 -            var index = ko.utils.arrayIndexOf(array, itemToRemove);
 183.113 -            if (index >= 0)
 183.114 -                array.splice(index, 1);
 183.115 -        },
 183.116 -
 183.117 -        arrayGetDistinctValues: function (array) {
 183.118 -            array = array || [];
 183.119 -            var result = [];
 183.120 -            for (var i = 0, j = array.length; i < j; i++) {
 183.121 -                if (ko.utils.arrayIndexOf(result, array[i]) < 0)
 183.122 -                    result.push(array[i]);
 183.123 -            }
 183.124 -            return result;
 183.125 -        },
 183.126 -
 183.127 -        arrayMap: function (array, mapping) {
 183.128 -            array = array || [];
 183.129 -            var result = [];
 183.130 -            for (var i = 0, j = array.length; i < j; i++)
 183.131 -                result.push(mapping(array[i]));
 183.132 -            return result;
 183.133 -        },
 183.134 -
 183.135 -        arrayFilter: function (array, predicate) {
 183.136 -            array = array || [];
 183.137 -            var result = [];
 183.138 -            for (var i = 0, j = array.length; i < j; i++)
 183.139 -                if (predicate(array[i]))
 183.140 -                    result.push(array[i]);
 183.141 -            return result;
 183.142 -        },
 183.143 -
 183.144 -        arrayPushAll: function (array, valuesToPush) {
 183.145 -            if (valuesToPush instanceof Array)
 183.146 -                array.push.apply(array, valuesToPush);
 183.147 -            else
 183.148 -                for (var i = 0, j = valuesToPush.length; i < j; i++)
 183.149 -                    array.push(valuesToPush[i]);
 183.150 -            return array;
 183.151 -        },
 183.152 -
 183.153 -        extend: function (target, source) {
 183.154 -            if (source) {
 183.155 -                for(var prop in source) {
 183.156 -                    if(source.hasOwnProperty(prop)) {
 183.157 -                        target[prop] = source[prop];
 183.158 -                    }
 183.159 -                }
 183.160 -            }
 183.161 -            return target;
 183.162 -        },
 183.163 -
 183.164 -        emptyDomNode: function (domNode) {
 183.165 -            while (domNode.firstChild) {
 183.166 -                ko.removeNode(domNode.firstChild);
 183.167 -            }
 183.168 -        },
 183.169 -
 183.170 -        moveCleanedNodesToContainerElement: function(nodes) {
 183.171 -            // Ensure it's a real array, as we're about to reparent the nodes and
 183.172 -            // we don't want the underlying collection to change while we're doing that.
 183.173 -            var nodesArray = ko.utils.makeArray(nodes);
 183.174 -
 183.175 -            var container = document.createElement('div');
 183.176 -            for (var i = 0, j = nodesArray.length; i < j; i++) {
 183.177 -                container.appendChild(ko.cleanNode(nodesArray[i]));
 183.178 -            }
 183.179 -            return container;
 183.180 -        },
 183.181 -
 183.182 -        cloneNodes: function (nodesArray, shouldCleanNodes) {
 183.183 -            for (var i = 0, j = nodesArray.length, newNodesArray = []; i < j; i++) {
 183.184 -                var clonedNode = nodesArray[i].cloneNode(true);
 183.185 -                newNodesArray.push(shouldCleanNodes ? ko.cleanNode(clonedNode) : clonedNode);
 183.186 -            }
 183.187 -            return newNodesArray;
 183.188 -        },
 183.189 -
 183.190 -        setDomNodeChildren: function (domNode, childNodes) {
 183.191 -            ko.utils.emptyDomNode(domNode);
 183.192 -            if (childNodes) {
 183.193 -                for (var i = 0, j = childNodes.length; i < j; i++)
 183.194 -                    domNode.appendChild(childNodes[i]);
 183.195 -            }
 183.196 -        },
 183.197 -
 183.198 -        replaceDomNodes: function (nodeToReplaceOrNodeArray, newNodesArray) {
 183.199 -            var nodesToReplaceArray = nodeToReplaceOrNodeArray.nodeType ? [nodeToReplaceOrNodeArray] : nodeToReplaceOrNodeArray;
 183.200 -            if (nodesToReplaceArray.length > 0) {
 183.201 -                var insertionPoint = nodesToReplaceArray[0];
 183.202 -                var parent = insertionPoint.parentNode;
 183.203 -                for (var i = 0, j = newNodesArray.length; i < j; i++)
 183.204 -                    parent.insertBefore(newNodesArray[i], insertionPoint);
 183.205 -                for (var i = 0, j = nodesToReplaceArray.length; i < j; i++) {
 183.206 -                    ko.removeNode(nodesToReplaceArray[i]);
 183.207 -                }
 183.208 -            }
 183.209 -        },
 183.210 -
 183.211 -        setOptionNodeSelectionState: function (optionNode, isSelected) {
 183.212 -            // IE6 sometimes throws "unknown error" if you try to write to .selected directly, whereas Firefox struggles with setAttribute. Pick one based on browser.
 183.213 -            if (ieVersion < 7)
 183.214 -                optionNode.setAttribute("selected", isSelected);
 183.215 -            else
 183.216 -                optionNode.selected = isSelected;
 183.217 -        },
 183.218 -
 183.219 -        stringTrim: function (string) {
 183.220 -            return (string || "").replace(stringTrimRegex, "");
 183.221 -        },
 183.222 -
 183.223 -        stringTokenize: function (string, delimiter) {
 183.224 -            var result = [];
 183.225 -            var tokens = (string || "").split(delimiter);
 183.226 -            for (var i = 0, j = tokens.length; i < j; i++) {
 183.227 -                var trimmed = ko.utils.stringTrim(tokens[i]);
 183.228 -                if (trimmed !== "")
 183.229 -                    result.push(trimmed);
 183.230 -            }
 183.231 -            return result;
 183.232 -        },
 183.233 -
 183.234 -        stringStartsWith: function (string, startsWith) {
 183.235 -            string = string || "";
 183.236 -            if (startsWith.length > string.length)
 183.237 -                return false;
 183.238 -            return string.substring(0, startsWith.length) === startsWith;
 183.239 -        },
 183.240 -
 183.241 -        domNodeIsContainedBy: function (node, containedByNode) {
 183.242 -            if (containedByNode.compareDocumentPosition)
 183.243 -                return (containedByNode.compareDocumentPosition(node) & 16) == 16;
 183.244 -            while (node != null) {
 183.245 -                if (node == containedByNode)
 183.246 -                    return true;
 183.247 -                node = node.parentNode;
 183.248 -            }
 183.249 -            return false;
 183.250 -        },
 183.251 -
 183.252 -        domNodeIsAttachedToDocument: function (node) {
 183.253 -            return ko.utils.domNodeIsContainedBy(node, node.ownerDocument);
 183.254 -        },
 183.255 -
 183.256 -        tagNameLower: function(element) {
 183.257 -            // For HTML elements, tagName will always be upper case; for XHTML elements, it'll be lower case.
 183.258 -            // Possible future optimization: If we know it's an element from an XHTML document (not HTML),
 183.259 -            // we don't need to do the .toLowerCase() as it will always be lower case anyway.
 183.260 -            return element && element.tagName && element.tagName.toLowerCase();
 183.261 -        },
 183.262 -
 183.263 -        registerEventHandler: function (element, eventType, handler) {
 183.264 -            var mustUseAttachEvent = ieVersion && eventsThatMustBeRegisteredUsingAttachEvent[eventType];
 183.265 -            if (!mustUseAttachEvent && typeof jQuery != "undefined") {
 183.266 -                if (isClickOnCheckableElement(element, eventType)) {
 183.267 -                    // For click events on checkboxes, jQuery interferes with the event handling in an awkward way:
 183.268 -                    // it toggles the element checked state *after* the click event handlers run, whereas native
 183.269 -                    // click events toggle the checked state *before* the event handler.
 183.270 -                    // Fix this by intecepting the handler and applying the correct checkedness before it runs.
 183.271 -                    var originalHandler = handler;
 183.272 -                    handler = function(event, eventData) {
 183.273 -                        var jQuerySuppliedCheckedState = this.checked;
 183.274 -                        if (eventData)
 183.275 -                            this.checked = eventData.checkedStateBeforeEvent !== true;
 183.276 -                        originalHandler.call(this, event);
 183.277 -                        this.checked = jQuerySuppliedCheckedState; // Restore the state jQuery applied
 183.278 -                    };
 183.279 -                }
 183.280 -                jQuery(element)['bind'](eventType, handler);
 183.281 -            } else if (!mustUseAttachEvent && typeof element.addEventListener == "function")
 183.282 -                element.addEventListener(eventType, handler, false);
 183.283 -            else if (typeof element.attachEvent != "undefined")
 183.284 -                element.attachEvent("on" + eventType, function (event) {
 183.285 -                    handler.call(element, event);
 183.286 -                });
 183.287 -            else
 183.288 -                throw new Error("Browser doesn't support addEventListener or attachEvent");
 183.289 -        },
 183.290 -
 183.291 -        triggerEvent: function (element, eventType) {
 183.292 -            if (!(element && element.nodeType))
 183.293 -                throw new Error("element must be a DOM node when calling triggerEvent");
 183.294 -
 183.295 -            if (typeof jQuery != "undefined") {
 183.296 -                var eventData = [];
 183.297 -                if (isClickOnCheckableElement(element, eventType)) {
 183.298 -                    // Work around the jQuery "click events on checkboxes" issue described above by storing the original checked state before triggering the handler
 183.299 -                    eventData.push({ checkedStateBeforeEvent: element.checked });
 183.300 -                }
 183.301 -                jQuery(element)['trigger'](eventType, eventData);
 183.302 -            } else if (typeof document.createEvent == "function") {
 183.303 -                if (typeof element.dispatchEvent == "function") {
 183.304 -                    var eventCategory = knownEventTypesByEventName[eventType] || "HTMLEvents";
 183.305 -                    var event = document.createEvent(eventCategory);
 183.306 -                    event.initEvent(eventType, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, element);
 183.307 -                    element.dispatchEvent(event);
 183.308 -                }
 183.309 -                else
 183.310 -                    throw new Error("The supplied element doesn't support dispatchEvent");
 183.311 -            } else if (typeof element.fireEvent != "undefined") {
 183.312 -                // Unlike other browsers, IE doesn't change the checked state of checkboxes/radiobuttons when you trigger their "click" event
 183.313 -                // so to make it consistent, we'll do it manually here
 183.314 -                if (isClickOnCheckableElement(element, eventType))
 183.315 -                    element.checked = element.checked !== true;
 183.316 -                element.fireEvent("on" + eventType);
 183.317 -            }
 183.318 -            else
 183.319 -                throw new Error("Browser doesn't support triggering events");
 183.320 -        },
 183.321 -
 183.322 -        unwrapObservable: function (value) {
 183.323 -            return ko.isObservable(value) ? value() : value;
 183.324 -        },
 183.325 -
 183.326 -        peekObservable: function (value) {
 183.327 -            return ko.isObservable(value) ? value.peek() : value;
 183.328 -        },
 183.329 -
 183.330 -        toggleDomNodeCssClass: function (node, classNames, shouldHaveClass) {
 183.331 -            if (classNames) {
 183.332 -                var cssClassNameRegex = /[\w-]+/g,
 183.333 -                    currentClassNames = node.className.match(cssClassNameRegex) || [];
 183.334 -                ko.utils.arrayForEach(classNames.match(cssClassNameRegex), function(className) {
 183.335 -                    var indexOfClass = ko.utils.arrayIndexOf(currentClassNames, className);
 183.336 -                    if (indexOfClass >= 0) {
 183.337 -                        if (!shouldHaveClass)
 183.338 -                            currentClassNames.splice(indexOfClass, 1);
 183.339 -                    } else {
 183.340 -                        if (shouldHaveClass)
 183.341 -                            currentClassNames.push(className);
 183.342 -                    }
 183.343 -                });
 183.344 -                node.className = currentClassNames.join(" ");
 183.345 -            }
 183.346 -        },
 183.347 -
 183.348 -        setTextContent: function(element, textContent) {
 183.349 -            var value = ko.utils.unwrapObservable(textContent);
 183.350 -            if ((value === null) || (value === undefined))
 183.351 -                value = "";
 183.352 -
 183.353 -            if (element.nodeType === 3) {
 183.354 -                element.data = value;
 183.355 -            } else {
 183.356 -                // We need there to be exactly one child: a text node.
 183.357 -                // If there are no children, more than one, or if it's not a text node,
 183.358 -                // we'll clear everything and create a single text node.
 183.359 -                var innerTextNode = ko.virtualElements.firstChild(element);
 183.360 -                if (!innerTextNode || innerTextNode.nodeType != 3 || ko.virtualElements.nextSibling(innerTextNode)) {
 183.361 -                    ko.virtualElements.setDomNodeChildren(element, [document.createTextNode(value)]);
 183.362 -                } else {
 183.363 -                    innerTextNode.data = value;
 183.364 -                }
 183.365 -
 183.366 -                ko.utils.forceRefresh(element);
 183.367 -            }
 183.368 -        },
 183.369 -
 183.370 -        setElementName: function(element, name) {
 183.371 -            element.name = name;
 183.372 -
 183.373 -            // Workaround IE 6/7 issue
 183.374 -            // - https://github.com/SteveSanderson/knockout/issues/197
 183.375 -            // - http://www.matts411.com/post/setting_the_name_attribute_in_ie_dom/
 183.376 -            if (ieVersion <= 7) {
 183.377 -                try {
 183.378 -                    element.mergeAttributes(document.createElement("<input name='" + element.name + "'/>"), false);
 183.379 -                }
 183.380 -                catch(e) {} // For IE9 with doc mode "IE9 Standards" and browser mode "IE9 Compatibility View"
 183.381 -            }
 183.382 -        },
 183.383 -
 183.384 -        forceRefresh: function(node) {
 183.385 -            // Workaround for an IE9 rendering bug - https://github.com/SteveSanderson/knockout/issues/209
 183.386 -            if (ieVersion >= 9) {
 183.387 -                // For text nodes and comment nodes (most likely virtual elements), we will have to refresh the container
 183.388 -                var elem = node.nodeType == 1 ? node : node.parentNode;
 183.389 -                if (elem.style)
 183.390 -                    elem.style.zoom = elem.style.zoom;
 183.391 -            }
 183.392 -        },
 183.393 -
 183.394 -        ensureSelectElementIsRenderedCorrectly: function(selectElement) {
 183.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.
 183.396 -            // (See https://github.com/SteveSanderson/knockout/issues/312, http://stackoverflow.com/questions/5908494/select-only-shows-first-char-of-selected-option)
 183.397 -            if (ieVersion >= 9) {
 183.398 -                var originalWidth = selectElement.style.width;
 183.399 -                selectElement.style.width = 0;
 183.400 -                selectElement.style.width = originalWidth;
 183.401 -            }
 183.402 -        },
 183.403 -
 183.404 -        range: function (min, max) {
 183.405 -            min = ko.utils.unwrapObservable(min);
 183.406 -            max = ko.utils.unwrapObservable(max);
 183.407 -            var result = [];
 183.408 -            for (var i = min; i <= max; i++)
 183.409 -                result.push(i);
 183.410 -            return result;
 183.411 -        },
 183.412 -
 183.413 -        makeArray: function(arrayLikeObject) {
 183.414 -            var result = [];
 183.415 -            for (var i = 0, j = arrayLikeObject.length; i < j; i++) {
 183.416 -                result.push(arrayLikeObject[i]);
 183.417 -            };
 183.418 -            return result;
 183.419 -        },
 183.420 -
 183.421 -        isIe6 : isIe6,
 183.422 -        isIe7 : isIe7,
 183.423 -        ieVersion : ieVersion,
 183.424 -
 183.425 -        getFormFields: function(form, fieldName) {
 183.426 -            var fields = ko.utils.makeArray(form.getElementsByTagName("input")).concat(ko.utils.makeArray(form.getElementsByTagName("textarea")));
 183.427 -            var isMatchingField = (typeof fieldName == 'string')
 183.428 -                ? function(field) { return field.name === fieldName }
 183.429 -                : function(field) { return fieldName.test(field.name) }; // Treat fieldName as regex or object containing predicate
 183.430 -            var matches = [];
 183.431 -            for (var i = fields.length - 1; i >= 0; i--) {
 183.432 -                if (isMatchingField(fields[i]))
 183.433 -                    matches.push(fields[i]);
 183.434 -            };
 183.435 -            return matches;
 183.436 -        },
 183.437 -
 183.438 -        parseJson: function (jsonString) {
 183.439 -            if (typeof jsonString == "string") {
 183.440 -                jsonString = ko.utils.stringTrim(jsonString);
 183.441 -                if (jsonString) {
 183.442 -                    if (window.JSON && window.JSON.parse) // Use native parsing where available
 183.443 -                        return window.JSON.parse(jsonString);
 183.444 -                    return (new Function("return " + jsonString))(); // Fallback on less safe parsing for older browsers
 183.445 -                }
 183.446 -            }
 183.447 -            return null;
 183.448 -        },
 183.449 -
 183.450 -        stringifyJson: function (data, replacer, space) {   // replacer and space are optional
 183.451 -            if ((typeof JSON == "undefined") || (typeof JSON.stringify == "undefined"))
 183.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");
 183.453 -            return JSON.stringify(ko.utils.unwrapObservable(data), replacer, space);
 183.454 -        },
 183.455 -
 183.456 -        postJson: function (urlOrForm, data, options) {
 183.457 -            options = options || {};
 183.458 -            var params = options['params'] || {};
 183.459 -            var includeFields = options['includeFields'] || this.fieldsIncludedWithJsonPost;
 183.460 -            var url = urlOrForm;
 183.461 -
 183.462 -            // If we were given a form, use its 'action' URL and pick out any requested field values
 183.463 -            if((typeof urlOrForm == 'object') && (ko.utils.tagNameLower(urlOrForm) === "form")) {
 183.464 -                var originalForm = urlOrForm;
 183.465 -                url = originalForm.action;
 183.466 -                for (var i = includeFields.length - 1; i >= 0; i--) {
 183.467 -                    var fields = ko.utils.getFormFields(originalForm, includeFields[i]);
 183.468 -                    for (var j = fields.length - 1; j >= 0; j--)
 183.469 -                        params[fields[j].name] = fields[j].value;
 183.470 -                }
 183.471 -            }
 183.472 -
 183.473 -            data = ko.utils.unwrapObservable(data);
 183.474 -            var form = document.createElement("form");
 183.475 -            form.style.display = "none";
 183.476 -            form.action = url;
 183.477 -            form.method = "post";
 183.478 -            for (var key in data) {
 183.479 -                var input = document.createElement("input");
 183.480 -                input.name = key;
 183.481 -                input.value = ko.utils.stringifyJson(ko.utils.unwrapObservable(data[key]));
 183.482 -                form.appendChild(input);
 183.483 -            }
 183.484 -            for (var key in params) {
 183.485 -                var input = document.createElement("input");
 183.486 -                input.name = key;
 183.487 -                input.value = params[key];
 183.488 -                form.appendChild(input);
 183.489 -            }
 183.490 -            document.body.appendChild(form);
 183.491 -            options['submitter'] ? options['submitter'](form) : form.submit();
 183.492 -            setTimeout(function () { form.parentNode.removeChild(form); }, 0);
 183.493 -        }
 183.494 -    }
 183.495 -})();
 183.496 -
 183.497 -ko.exportSymbol('utils', ko.utils);
 183.498 -ko.exportSymbol('utils.arrayForEach', ko.utils.arrayForEach);
 183.499 -ko.exportSymbol('utils.arrayFirst', ko.utils.arrayFirst);
 183.500 -ko.exportSymbol('utils.arrayFilter', ko.utils.arrayFilter);
 183.501 -ko.exportSymbol('utils.arrayGetDistinctValues', ko.utils.arrayGetDistinctValues);
 183.502 -ko.exportSymbol('utils.arrayIndexOf', ko.utils.arrayIndexOf);
 183.503 -ko.exportSymbol('utils.arrayMap', ko.utils.arrayMap);
 183.504 -ko.exportSymbol('utils.arrayPushAll', ko.utils.arrayPushAll);
 183.505 -ko.exportSymbol('utils.arrayRemoveItem', ko.utils.arrayRemoveItem);
 183.506 -ko.exportSymbol('utils.extend', ko.utils.extend);
 183.507 -ko.exportSymbol('utils.fieldsIncludedWithJsonPost', ko.utils.fieldsIncludedWithJsonPost);
 183.508 -ko.exportSymbol('utils.getFormFields', ko.utils.getFormFields);
 183.509 -ko.exportSymbol('utils.peekObservable', ko.utils.peekObservable);
 183.510 -ko.exportSymbol('utils.postJson', ko.utils.postJson);
 183.511 -ko.exportSymbol('utils.parseJson', ko.utils.parseJson);
 183.512 -ko.exportSymbol('utils.registerEventHandler', ko.utils.registerEventHandler);
 183.513 -ko.exportSymbol('utils.stringifyJson', ko.utils.stringifyJson);
 183.514 -ko.exportSymbol('utils.range', ko.utils.range);
 183.515 -ko.exportSymbol('utils.toggleDomNodeCssClass', ko.utils.toggleDomNodeCssClass);
 183.516 -ko.exportSymbol('utils.triggerEvent', ko.utils.triggerEvent);
 183.517 -ko.exportSymbol('utils.unwrapObservable', ko.utils.unwrapObservable);
 183.518 -
 183.519 -if (!Function.prototype['bind']) {
 183.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)
 183.521 -    // In case the browser doesn't implement it natively, provide a JavaScript implementation. This implementation is based on the one in prototype.js
 183.522 -    Function.prototype['bind'] = function (object) {
 183.523 -        var originalFunction = this, args = Array.prototype.slice.call(arguments), object = args.shift();
 183.524 -        return function () {
 183.525 -            return originalFunction.apply(object, args.concat(Array.prototype.slice.call(arguments)));
 183.526 -        };
 183.527 -    };
 183.528 -}
 183.529 -
 183.530 -ko.utils.domData = new (function () {
 183.531 -    var uniqueId = 0;
 183.532 -    var dataStoreKeyExpandoPropertyName = "__ko__" + (new Date).getTime();
 183.533 -    var dataStore = {};
 183.534 -    return {
 183.535 -        get: function (node, key) {
 183.536 -            var allDataForNode = ko.utils.domData.getAll(node, false);
 183.537 -            return allDataForNode === undefined ? undefined : allDataForNode[key];
 183.538 -        },
 183.539 -        set: function (node, key, value) {
 183.540 -            if (value === undefined) {
 183.541 -                // Make sure we don't actually create a new domData key if we are actually deleting a value
 183.542 -                if (ko.utils.domData.getAll(node, false) === undefined)
 183.543 -                    return;
 183.544 -            }
 183.545 -            var allDataForNode = ko.utils.domData.getAll(node, true);
 183.546 -            allDataForNode[key] = value;
 183.547 -        },
 183.548 -        getAll: function (node, createIfNotFound) {
 183.549 -            var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
 183.550 -            var hasExistingDataStore = dataStoreKey && (dataStoreKey !== "null") && dataStore[dataStoreKey];
 183.551 -            if (!hasExistingDataStore) {
 183.552 -                if (!createIfNotFound)
 183.553 -                    return undefined;
 183.554 -                dataStoreKey = node[dataStoreKeyExpandoPropertyName] = "ko" + uniqueId++;
 183.555 -                dataStore[dataStoreKey] = {};
 183.556 -            }
 183.557 -            return dataStore[dataStoreKey];
 183.558 -        },
 183.559 -        clear: function (node) {
 183.560 -            var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
 183.561 -            if (dataStoreKey) {
 183.562 -                delete dataStore[dataStoreKey];
 183.563 -                node[dataStoreKeyExpandoPropertyName] = null;
 183.564 -                return true; // Exposing "did clean" flag purely so specs can infer whether things have been cleaned up as intended
 183.565 -            }
 183.566 -            return false;
 183.567 -        }
 183.568 -    }
 183.569 -})();
 183.570 -
 183.571 -ko.exportSymbol('utils.domData', ko.utils.domData);
 183.572 -ko.exportSymbol('utils.domData.clear', ko.utils.domData.clear); // Exporting only so specs can clear up after themselves fully
 183.573 -
 183.574 -ko.utils.domNodeDisposal = new (function () {
 183.575 -    var domDataKey = "__ko_domNodeDisposal__" + (new Date).getTime();
 183.576 -    var cleanableNodeTypes = { 1: true, 8: true, 9: true };       // Element, Comment, Document
 183.577 -    var cleanableNodeTypesWithDescendants = { 1: true, 9: true }; // Element, Document
 183.578 -
 183.579 -    function getDisposeCallbacksCollection(node, createIfNotFound) {
 183.580 -        var allDisposeCallbacks = ko.utils.domData.get(node, domDataKey);
 183.581 -        if ((allDisposeCallbacks === undefined) && createIfNotFound) {
 183.582 -            allDisposeCallbacks = [];
 183.583 -            ko.utils.domData.set(node, domDataKey, allDisposeCallbacks);
 183.584 -        }
 183.585 -        return allDisposeCallbacks;
 183.586 -    }
 183.587 -    function destroyCallbacksCollection(node) {
 183.588 -        ko.utils.domData.set(node, domDataKey, undefined);
 183.589 -    }
 183.590 -
 183.591 -    function cleanSingleNode(node) {
 183.592 -        // Run all the dispose callbacks
 183.593 -        var callbacks = getDisposeCallbacksCollection(node, false);
 183.594 -        if (callbacks) {
 183.595 -            callbacks = callbacks.slice(0); // Clone, as the array may be modified during iteration (typically, callbacks will remove themselves)
 183.596 -            for (var i = 0; i < callbacks.length; i++)
 183.597 -                callbacks[i](node);
 183.598 -        }
 183.599 -
 183.600 -        // Also erase the DOM data
 183.601 -        ko.utils.domData.clear(node);
 183.602 -
 183.603 -        // Special support for jQuery here because it's so commonly used.
 183.604 -        // Many jQuery plugins (including jquery.tmpl) store data using jQuery's equivalent of domData
 183.605 -        // so notify it to tear down any resources associated with the node & descendants here.
 183.606 -        if ((typeof jQuery == "function") && (typeof jQuery['cleanData'] == "function"))
 183.607 -            jQuery['cleanData']([node]);
 183.608 -
 183.609 -        // Also clear any immediate-child comment nodes, as these wouldn't have been found by
 183.610 -        // node.getElementsByTagName("*") in cleanNode() (comment nodes aren't elements)
 183.611 -        if (cleanableNodeTypesWithDescendants[node.nodeType])
 183.612 -            cleanImmediateCommentTypeChildren(node);
 183.613 -    }
 183.614 -
 183.615 -    function cleanImmediateCommentTypeChildren(nodeWithChildren) {
 183.616 -        var child, nextChild = nodeWithChildren.firstChild;
 183.617 -        while (child = nextChild) {
 183.618 -            nextChild = child.nextSibling;
 183.619 -            if (child.nodeType === 8)
 183.620 -                cleanSingleNode(child);
 183.621 -        }
 183.622 -    }
 183.623 -
 183.624 -    return {
 183.625 -        addDisposeCallback : function(node, callback) {
 183.626 -            if (typeof callback != "function")
 183.627 -                throw new Error("Callback must be a function");
 183.628 -            getDisposeCallbacksCollection(node, true).push(callback);
 183.629 -        },
 183.630 -
 183.631 -        removeDisposeCallback : function(node, callback) {
 183.632 -            var callbacksCollection = getDisposeCallbacksCollection(node, false);
 183.633 -            if (callbacksCollection) {
 183.634 -                ko.utils.arrayRemoveItem(callbacksCollection, callback);
 183.635 -                if (callbacksCollection.length == 0)
 183.636 -                    destroyCallbacksCollection(node);
 183.637 -            }
 183.638 -        },
 183.639 -
 183.640 -        cleanNode : function(node) {
 183.641 -            // First clean this node, where applicable
 183.642 -            if (cleanableNodeTypes[node.nodeType]) {
 183.643 -                cleanSingleNode(node);
 183.644 -
 183.645 -                // ... then its descendants, where applicable
 183.646 -                if (cleanableNodeTypesWithDescendants[node.nodeType]) {
 183.647 -                    // Clone the descendants list in case it changes during iteration
 183.648 -                    var descendants = [];
 183.649 -                    ko.utils.arrayPushAll(descendants, node.getElementsByTagName("*"));
 183.650 -                    for (var i = 0, j = descendants.length; i < j; i++)
 183.651 -                        cleanSingleNode(descendants[i]);
 183.652 -                }
 183.653 -            }
 183.654 -            return node;
 183.655 -        },
 183.656 -
 183.657 -        removeNode : function(node) {
 183.658 -            ko.cleanNode(node);
 183.659 -            if (node.parentNode)
 183.660 -                node.parentNode.removeChild(node);
 183.661 -        }
 183.662 -    }
 183.663 -})();
 183.664 -ko.cleanNode = ko.utils.domNodeDisposal.cleanNode; // Shorthand name for convenience
 183.665 -ko.removeNode = ko.utils.domNodeDisposal.removeNode; // Shorthand name for convenience
 183.666 -ko.exportSymbol('cleanNode', ko.cleanNode);
 183.667 -ko.exportSymbol('removeNode', ko.removeNode);
 183.668 -ko.exportSymbol('utils.domNodeDisposal', ko.utils.domNodeDisposal);
 183.669 -ko.exportSymbol('utils.domNodeDisposal.addDisposeCallback', ko.utils.domNodeDisposal.addDisposeCallback);
 183.670 -ko.exportSymbol('utils.domNodeDisposal.removeDisposeCallback', ko.utils.domNodeDisposal.removeDisposeCallback);
 183.671 -(function () {
 183.672 -    var leadingCommentRegex = /^(\s*)<!--(.*?)-->/;
 183.673 -
 183.674 -    function simpleHtmlParse(html) {
 183.675 -        // Based on jQuery's "clean" function, but only accounting for table-related elements.
 183.676 -        // If you have referenced jQuery, this won't be used anyway - KO will use jQuery's "clean" function directly
 183.677 -
 183.678 -        // Note that there's still an issue in IE < 9 whereby it will discard comment nodes that are the first child of
 183.679 -        // a descendant node. For example: "<div><!-- mycomment -->abc</div>" will get parsed as "<div>abc</div>"
 183.680 -        // This won't affect anyone who has referenced jQuery, and there's always the workaround of inserting a dummy node
 183.681 -        // (possibly a text node) in front of the comment. So, KO does not attempt to workaround this IE issue automatically at present.
 183.682 -
 183.683 -        // Trim whitespace, otherwise indexOf won't work as expected
 183.684 -        var tags = ko.utils.stringTrim(html).toLowerCase(), div = document.createElement("div");
 183.685 -
 183.686 -        // Finds the first match from the left column, and returns the corresponding "wrap" data from the right column
 183.687 -        var wrap = tags.match(/^<(thead|tbody|tfoot)/)              && [1, "<table>", "</table>"] ||
 183.688 -                   !tags.indexOf("<tr")                             && [2, "<table><tbody>", "</tbody></table>"] ||
 183.689 -                   (!tags.indexOf("<td") || !tags.indexOf("<th"))   && [3, "<table><tbody><tr>", "</tr></tbody></table>"] ||
 183.690 -                   /* anything else */                                 [0, "", ""];
 183.691 -
 183.692 -        // Go to html and back, then peel off extra wrappers
 183.693 -        // Note that we always prefix with some dummy text, because otherwise, IE<9 will strip out leading comment nodes in descendants. Total madness.
 183.694 -        var markup = "ignored<div>" + wrap[1] + html + wrap[2] + "</div>";
 183.695 -        if (typeof window['innerShiv'] == "function") {
 183.696 -            div.appendChild(window['innerShiv'](markup));
 183.697 -        } else {
 183.698 -            div.innerHTML = markup;
 183.699 -        }
 183.700 -
 183.701 -        // Move to the right depth
 183.702 -        while (wrap[0]--)
 183.703 -            div = div.lastChild;
 183.704 -
 183.705 -        return ko.utils.makeArray(div.lastChild.childNodes);
 183.706 -    }
 183.707 -
 183.708 -    function jQueryHtmlParse(html) {
 183.709 -        // jQuery's "parseHTML" function was introduced in jQuery 1.8.0 and is a documented public API.
 183.710 -        if (jQuery['parseHTML']) {
 183.711 -            return jQuery['parseHTML'](html);
 183.712 -        } else {
 183.713 -            // For jQuery < 1.8.0, we fall back on the undocumented internal "clean" function.
 183.714 -            var elems = jQuery['clean']([html]);
 183.715 -
 183.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.
 183.717 -            // Unfortunately, it never clears the dummy parent nodes from the document fragment, so it leaks memory over time.
 183.718 -            // Fix this by finding the top-most dummy parent element, and detaching it from its owner fragment.
 183.719 -            if (elems && elems[0]) {
 183.720 -                // Find the top-most parent element that's a direct child of a document fragment
 183.721 -                var elem = elems[0];
 183.722 -                while (elem.parentNode && elem.parentNode.nodeType !== 11 /* i.e., DocumentFragment */)
 183.723 -                    elem = elem.parentNode;
 183.724 -                // ... then detach it
 183.725 -                if (elem.parentNode)
 183.726 -                    elem.parentNode.removeChild(elem);
 183.727 -            }
 183.728 -
 183.729 -            return elems;
 183.730 -        }
 183.731 -    }
 183.732 -
 183.733 -    ko.utils.parseHtmlFragment = function(html) {
 183.734 -        return typeof jQuery != 'undefined' ? jQueryHtmlParse(html)   // As below, benefit from jQuery's optimisations where possible
 183.735 -                                            : simpleHtmlParse(html);  // ... otherwise, this simple logic will do in most common cases.
 183.736 -    };
 183.737 -
 183.738 -    ko.utils.setHtml = function(node, html) {
 183.739 -        ko.utils.emptyDomNode(node);
 183.740 -
 183.741 -        // There's no legitimate reason to display a stringified observable without unwrapping it, so we'll unwrap it
 183.742 -        html = ko.utils.unwrapObservable(html);
 183.743 -
 183.744 -        if ((html !== null) && (html !== undefined)) {
 183.745 -            if (typeof html != 'string')
 183.746 -                html = html.toString();
 183.747 -
 183.748 -            // jQuery contains a lot of sophisticated code to parse arbitrary HTML fragments,
 183.749 -            // for example <tr> elements which are not normally allowed to exist on their own.
 183.750 -            // If you've referenced jQuery we'll use that rather than duplicating its code.
 183.751 -            if (typeof jQuery != 'undefined') {
 183.752 -                jQuery(node)['html'](html);
 183.753 -            } else {
 183.754 -                // ... otherwise, use KO's own parsing logic.
 183.755 -                var parsedNodes = ko.utils.parseHtmlFragment(html);
 183.756 -                for (var i = 0; i < parsedNodes.length; i++)
 183.757 -                    node.appendChild(parsedNodes[i]);
 183.758 -            }
 183.759 -        }
 183.760 -    };
 183.761 -})();
 183.762 -
 183.763 -ko.exportSymbol('utils.parseHtmlFragment', ko.utils.parseHtmlFragment);
 183.764 -ko.exportSymbol('utils.setHtml', ko.utils.setHtml);
 183.765 -
 183.766 -ko.memoization = (function () {
 183.767 -    var memos = {};
 183.768 -
 183.769 -    function randomMax8HexChars() {
 183.770 -        return (((1 + Math.random()) * 0x100000000) | 0).toString(16).substring(1);
 183.771 -    }
 183.772 -    function generateRandomId() {
 183.773 -        return randomMax8HexChars() + randomMax8HexChars();
 183.774 -    }
 183.775 -    function findMemoNodes(rootNode, appendToArray) {
 183.776 -        if (!rootNode)
 183.777 -            return;
 183.778 -        if (rootNode.nodeType == 8) {
 183.779 -            var memoId = ko.memoization.parseMemoText(rootNode.nodeValue);
 183.780 -            if (memoId != null)
 183.781 -                appendToArray.push({ domNode: rootNode, memoId: memoId });
 183.782 -        } else if (rootNode.nodeType == 1) {
 183.783 -            for (var i = 0, childNodes = rootNode.childNodes, j = childNodes.length; i < j; i++)
 183.784 -                findMemoNodes(childNodes[i], appendToArray);
 183.785 -        }
 183.786 -    }
 183.787 -
 183.788 -    return {
 183.789 -        memoize: function (callback) {
 183.790 -            if (typeof callback != "function")
 183.791 -                throw new Error("You can only pass a function to ko.memoization.memoize()");
 183.792 -            var memoId = generateRandomId();
 183.793 -            memos[memoId] = callback;
 183.794 -            return "<!--[ko_memo:" + memoId + "]-->";
 183.795 -        },
 183.796 -
 183.797 -        unmemoize: function (memoId, callbackParams) {
 183.798 -            var callback = memos[memoId];
 183.799 -            if (callback === undefined)
 183.800 -                throw new Error("Couldn't find any memo with ID " + memoId + ". Perhaps it's already been unmemoized.");
 183.801 -            try {
 183.802 -                callback.apply(null, callbackParams || []);
 183.803 -                return true;
 183.804 -            }
 183.805 -            finally { delete memos[memoId]; }
 183.806 -        },
 183.807 -
 183.808 -        unmemoizeDomNodeAndDescendants: function (domNode, extraCallbackParamsArray) {
 183.809 -            var memos = [];
 183.810 -            findMemoNodes(domNode, memos);
 183.811 -            for (var i = 0, j = memos.length; i < j; i++) {
 183.812 -                var node = memos[i].domNode;
 183.813 -                var combinedParams = [node];
 183.814 -                if (extraCallbackParamsArray)
 183.815 -                    ko.utils.arrayPushAll(combinedParams, extraCallbackParamsArray);
 183.816 -                ko.memoization.unmemoize(memos[i].memoId, combinedParams);
 183.817 -                node.nodeValue = ""; // Neuter this node so we don't try to unmemoize it again
 183.818 -                if (node.parentNode)
 183.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)
 183.820 -            }
 183.821 -        },
 183.822 -
 183.823 -        parseMemoText: function (memoText) {
 183.824 -            var match = memoText.match(/^\[ko_memo\:(.*?)\]$/);
 183.825 -            return match ? match[1] : null;
 183.826 -        }
 183.827 -    };
 183.828 -})();
 183.829 -
 183.830 -ko.exportSymbol('memoization', ko.memoization);
 183.831 -ko.exportSymbol('memoization.memoize', ko.memoization.memoize);
 183.832 -ko.exportSymbol('memoization.unmemoize', ko.memoization.unmemoize);
 183.833 -ko.exportSymbol('memoization.parseMemoText', ko.memoization.parseMemoText);
 183.834 -ko.exportSymbol('memoization.unmemoizeDomNodeAndDescendants', ko.memoization.unmemoizeDomNodeAndDescendants);
 183.835 -ko.extenders = {
 183.836 -    'throttle': function(target, timeout) {
 183.837 -        // Throttling means two things:
 183.838 -
 183.839 -        // (1) For dependent observables, we throttle *evaluations* so that, no matter how fast its dependencies
 183.840 -        //     notify updates, the target doesn't re-evaluate (and hence doesn't notify) faster than a certain rate
 183.841 -        target['throttleEvaluation'] = timeout;
 183.842 -
 183.843 -        // (2) For writable targets (observables, or writable dependent observables), we throttle *writes*
 183.844 -        //     so the target cannot change value synchronously or faster than a certain rate
 183.845 -        var writeTimeoutInstance = null;
 183.846 -        return ko.dependentObservable({
 183.847 -            'read': target,
 183.848 -            'write': function(value) {
 183.849 -                clearTimeout(writeTimeoutInstance);
 183.850 -                writeTimeoutInstance = setTimeout(function() {
 183.851 -                    target(value);
 183.852 -                }, timeout);
 183.853 -            }
 183.854 -        });
 183.855 -    },
 183.856 -
 183.857 -    'notify': function(target, notifyWhen) {
 183.858 -        target["equalityComparer"] = notifyWhen == "always"
 183.859 -            ? function() { return false } // Treat all values as not equal
 183.860 -            : ko.observable["fn"]["equalityComparer"];
 183.861 -        return target;
 183.862 -    }
 183.863 -};
 183.864 -
 183.865 -function applyExtenders(requestedExtenders) {
 183.866 -    var target = this;
 183.867 -    if (requestedExtenders) {
 183.868 -        for (var key in requestedExtenders) {
 183.869 -            var extenderHandler = ko.extenders[key];
 183.870 -            if (typeof extenderHandler == 'function') {
 183.871 -                target = extenderHandler(target, requestedExtenders[key]);
 183.872 -            }
 183.873 -        }
 183.874 -    }
 183.875 -    return target;
 183.876 -}
 183.877 -
 183.878 -ko.exportSymbol('extenders', ko.extenders);
 183.879 -
 183.880 -ko.subscription = function (target, callback, disposeCallback) {
 183.881 -    this.target = target;
 183.882 -    this.callback = callback;
 183.883 -    this.disposeCallback = disposeCallback;
 183.884 -    ko.exportProperty(this, 'dispose', this.dispose);
 183.885 -};
 183.886 -ko.subscription.prototype.dispose = function () {
 183.887 -    this.isDisposed = true;
 183.888 -    this.disposeCallback();
 183.889 -};
 183.890 -
 183.891 -ko.subscribable = function () {
 183.892 -    this._subscriptions = {};
 183.893 -
 183.894 -    ko.utils.extend(this, ko.subscribable['fn']);
 183.895 -    ko.exportProperty(this, 'subscribe', this.subscribe);
 183.896 -    ko.exportProperty(this, 'extend', this.extend);
 183.897 -    ko.exportProperty(this, 'getSubscriptionsCount', this.getSubscriptionsCount);
 183.898 -}
 183.899 -
 183.900 -var defaultEvent = "change";
 183.901 -
 183.902 -ko.subscribable['fn'] = {
 183.903 -    subscribe: function (callback, callbackTarget, event) {
 183.904 -        event = event || defaultEvent;
 183.905 -        var boundCallback = callbackTarget ? callback.bind(callbackTarget) : callback;
 183.906 -
 183.907 -        var subscription = new ko.subscription(this, boundCallback, function () {
 183.908 -            ko.utils.arrayRemoveItem(this._subscriptions[event], subscription);
 183.909 -        }.bind(this));
 183.910 -
 183.911 -        if (!this._subscriptions[event])
 183.912 -            this._subscriptions[event] = [];
 183.913 -        this._subscriptions[event].push(subscription);
 183.914 -        return subscription;
 183.915 -    },
 183.916 -
 183.917 -    "notifySubscribers": function (valueToNotify, event) {
 183.918 -        event = event || defaultEvent;
 183.919 -        if (this._subscriptions[event]) {
 183.920 -            ko.dependencyDetection.ignore(function() {
 183.921 -                ko.utils.arrayForEach(this._subscriptions[event].slice(0), function (subscription) {
 183.922 -                    // In case a subscription was disposed during the arrayForEach cycle, check
 183.923 -                    // for isDisposed on each subscription before invoking its callback
 183.924 -                    if (subscription && (subscription.isDisposed !== true))
 183.925 -                        subscription.callback(valueToNotify);
 183.926 -                });
 183.927 -            }, this);
 183.928 -        }
 183.929 -    },
 183.930 -
 183.931 -    getSubscriptionsCount: function () {
 183.932 -        var total = 0;
 183.933 -        for (var eventName in this._subscriptions) {
 183.934 -            if (this._subscriptions.hasOwnProperty(eventName))
 183.935 -                total += this._subscriptions[eventName].length;
 183.936 -        }
 183.937 -        return total;
 183.938 -    },
 183.939 -
 183.940 -    extend: applyExtenders
 183.941 -};
 183.942 -
 183.943 -
 183.944 -ko.isSubscribable = function (instance) {
 183.945 -    return typeof instance.subscribe == "function" && typeof instance["notifySubscribers"] == "function";
 183.946 -};
 183.947 -
 183.948 -ko.exportSymbol('subscribable', ko.subscribable);
 183.949 -ko.exportSymbol('isSubscribable', ko.isSubscribable);
 183.950 -
 183.951 -ko.dependencyDetection = (function () {
 183.952 -    var _frames = [];
 183.953 -
 183.954 -    return {
 183.955 -        begin: function (callback) {
 183.956 -            _frames.push({ callback: callback, distinctDependencies:[] });
 183.957 -        },
 183.958 -
 183.959 -        end: function () {
 183.960 -            _frames.pop();
 183.961 -        },
 183.962 -
 183.963 -        registerDependency: function (subscribable) {
 183.964 -            if (!ko.isSubscribable(subscribable))
 183.965 -                throw new Error("Only subscribable things can act as dependencies");
 183.966 -            if (_frames.length > 0) {
 183.967 -                var topFrame = _frames[_frames.length - 1];
 183.968 -                if (!topFrame || ko.utils.arrayIndexOf(topFrame.distinctDependencies, subscribable) >= 0)
 183.969 -                    return;
 183.970 -                topFrame.distinctDependencies.push(subscribable);
 183.971 -                topFrame.callback(subscribable);
 183.972 -            }
 183.973 -        },
 183.974 -
 183.975 -        ignore: function(callback, callbackTarget, callbackArgs) {
 183.976 -            try {
 183.977 -                _frames.push(null);
 183.978 -                return callback.apply(callbackTarget, callbackArgs || []);
 183.979 -            } finally {
 183.980 -                _frames.pop();
 183.981 -            }
 183.982 -        }
 183.983 -    };
 183.984 -})();
 183.985 -var primitiveTypes = { 'undefined':true, 'boolean':true, 'number':true, 'string':true };
 183.986 -
 183.987 -ko.observable = function (initialValue) {
 183.988 -    var _latestValue = initialValue;
 183.989 -
 183.990 -    function observable() {
 183.991 -        if (arguments.length > 0) {
 183.992 -            // Write
 183.993 -
 183.994 -            // Ignore writes if the value hasn't changed
 183.995 -            if ((!observable['equalityComparer']) || !observable['equalityComparer'](_latestValue, arguments[0])) {
 183.996 -                observable.valueWillMutate();
 183.997 -                _latestValue = arguments[0];
 183.998 -                if (DEBUG) observable._latestValue = _latestValue;
 183.999 -                observable.valueHasMutated();
183.1000 -            }
183.1001 -            return this; // Permits chained assignments
183.1002 -        }
183.1003 -        else {
183.1004 -            // Read
183.1005 -            ko.dependencyDetection.registerDependency(observable); // The caller only needs to be notified of changes if they did a "read" operation
183.1006 -            return _latestValue;
183.1007 -        }
183.1008 -    }
183.1009 -    if (DEBUG) observable._latestValue = _latestValue;
183.1010 -    ko.subscribable.call(observable);
183.1011 -    observable.peek = function() { return _latestValue };
183.1012 -    observable.valueHasMutated = function () { observable["notifySubscribers"](_latestValue); }
183.1013 -    observable.valueWillMutate = function () { observable["notifySubscribers"](_latestValue, "beforeChange"); }
183.1014 -    ko.utils.extend(observable, ko.observable['fn']);
183.1015 -
183.1016 -    ko.exportProperty(observable, 'peek', observable.peek);
183.1017 -    ko.exportProperty(observable, "valueHasMutated", observable.valueHasMutated);
183.1018 -    ko.exportProperty(observable, "valueWillMutate", observable.valueWillMutate);
183.1019 -
183.1020 -    return observable;
183.1021 -}
183.1022 -
183.1023 -ko.observable['fn'] = {
183.1024 -    "equalityComparer": function valuesArePrimitiveAndEqual(a, b) {
183.1025 -        var oldValueIsPrimitive = (a === null) || (typeof(a) in primitiveTypes);
183.1026 -        return oldValueIsPrimitive ? (a === b) : false;
183.1027 -    }
183.1028 -};
183.1029 -
183.1030 -var protoProperty = ko.observable.protoProperty = "__ko_proto__";
183.1031 -ko.observable['fn'][protoProperty] = ko.observable;
183.1032 -
183.1033 -ko.hasPrototype = function(instance, prototype) {
183.1034 -    if ((instance === null) || (instance === undefined) || (instance[protoProperty] === undefined)) return false;
183.1035 -    if (instance[protoProperty] === prototype) return true;
183.1036 -    return ko.hasPrototype(instance[protoProperty], prototype); // Walk the prototype chain
183.1037 -};
183.1038 -
183.1039 -ko.isObservable = function (instance) {
183.1040 -    return ko.hasPrototype(instance, ko.observable);
183.1041 -}
183.1042 -ko.isWriteableObservable = function (instance) {
183.1043 -    // Observable
183.1044 -    if ((typeof instance == "function") && instance[protoProperty] === ko.observable)
183.1045 -        return true;
183.1046 -    // Writeable dependent observable
183.1047 -    if ((typeof instance == "function") && (instance[protoProperty] === ko.dependentObservable) && (instance.hasWriteFunction))
183.1048 -        return true;
183.1049 -    // Anything else
183.1050 -    return false;
183.1051 -}
183.1052 -
183.1053 -
183.1054 -ko.exportSymbol('observable', ko.observable);
183.1055 -ko.exportSymbol('isObservable', ko.isObservable);
183.1056 -ko.exportSymbol('isWriteableObservable', ko.isWriteableObservable);
183.1057 -ko.observableArray = function (initialValues) {
183.1058 -    if (arguments.length == 0) {
183.1059 -        // Zero-parameter constructor initializes to empty array
183.1060 -        initialValues = [];
183.1061 -    }
183.1062 -    if ((initialValues !== null) && (initialValues !== undefined) && !('length' in initialValues))
183.1063 -        throw new Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");
183.1064 -
183.1065 -    var result = ko.observable(initialValues);
183.1066 -    ko.utils.extend(result, ko.observableArray['fn']);
183.1067 -    return result;
183.1068 -}
183.1069 -
183.1070 -ko.observableArray['fn'] = {
183.1071 -    'remove': function (valueOrPredicate) {
183.1072 -        var underlyingArray = this.peek();
183.1073 -        var removedValues = [];
183.1074 -        var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
183.1075 -        for (var i = 0; i < underlyingArray.length; i++) {
183.1076 -            var value = underlyingArray[i];
183.1077 -            if (predicate(value)) {
183.1078 -                if (removedValues.length === 0) {
183.1079 -                    this.valueWillMutate();
183.1080 -                }
183.1081 -                removedValues.push(value);
183.1082 -                underlyingArray.splice(i, 1);
183.1083 -                i--;
183.1084 -            }
183.1085 -        }
183.1086 -        if (removedValues.length) {
183.1087 -            this.valueHasMutated();
183.1088 -        }
183.1089 -        return removedValues;
183.1090 -    },
183.1091 -
183.1092 -    'removeAll': function (arrayOfValues) {
183.1093 -        // If you passed zero args, we remove everything
183.1094 -        if (arrayOfValues === undefined) {
183.1095 -            var underlyingArray = this.peek();
183.1096 -            var allValues = underlyingArray.slice(0);
183.1097 -            this.valueWillMutate();
183.1098 -            underlyingArray.splice(0, underlyingArray.length);
183.1099 -            this.valueHasMutated();
183.1100 -            return allValues;
183.1101 -        }
183.1102 -        // If you passed an arg, we interpret it as an array of entries to remove
183.1103 -        if (!arrayOfValues)
183.1104 -            return [];
183.1105 -        return this['remove'](function (value) {
183.1106 -            return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
183.1107 -        });
183.1108 -    },
183.1109 -
183.1110 -    'destroy': function (valueOrPredicate) {
183.1111 -        var underlyingArray = this.peek();
183.1112 -        var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
183.1113 -        this.valueWillMutate();
183.1114 -        for (var i = underlyingArray.length - 1; i >= 0; i--) {
183.1115 -            var value = underlyingArray[i];
183.1116 -            if (predicate(value))
183.1117 -                underlyingArray[i]["_destroy"] = true;
183.1118 -        }
183.1119 -        this.valueHasMutated();
183.1120 -    },
183.1121 -
183.1122 -    'destroyAll': function (arrayOfValues) {
183.1123 -        // If you passed zero args, we destroy everything
183.1124 -        if (arrayOfValues === undefined)
183.1125 -            return this['destroy'](function() { return true });
183.1126 -
183.1127 -        // If you passed an arg, we interpret it as an array of entries to destroy
183.1128 -        if (!arrayOfValues)
183.1129 -            return [];
183.1130 -        return this['destroy'](function (value) {
183.1131 -            return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
183.1132 -        });
183.1133 -    },
183.1134 -
183.1135 -    'indexOf': function (item) {
183.1136 -        var underlyingArray = this();
183.1137 -        return ko.utils.arrayIndexOf(underlyingArray, item);
183.1138 -    },
183.1139 -
183.1140 -    'replace': function(oldItem, newItem) {
183.1141 -        var index = this['indexOf'](oldItem);
183.1142 -        if (index >= 0) {
183.1143 -            this.valueWillMutate();
183.1144 -            this.peek()[index] = newItem;
183.1145 -            this.valueHasMutated();
183.1146 -        }
183.1147 -    }
183.1148 -}
183.1149 -
183.1150 -// Populate ko.observableArray.fn with read/write functions from native arrays
183.1151 -// Important: Do not add any additional functions here that may reasonably be used to *read* data from the array
183.1152 -// because we'll eval them without causing subscriptions, so ko.computed output could end up getting stale
183.1153 -ko.utils.arrayForEach(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function (methodName) {
183.1154 -    ko.observableArray['fn'][methodName] = function () {
183.1155 -        // Use "peek" to avoid creating a subscription in any computed that we're executing in the context of
183.1156 -        // (for consistency with mutating regular observables)
183.1157 -        var underlyingArray = this.peek();
183.1158 -        this.valueWillMutate();
183.1159 -        var methodCallResult = underlyingArray[methodName].apply(underlyingArray, arguments);
183.1160 -        this.valueHasMutated();
183.1161 -        return methodCallResult;
183.1162 -    };
183.1163 -});
183.1164 -
183.1165 -// Populate ko.observableArray.fn with read-only functions from native arrays
183.1166 -ko.utils.arrayForEach(["slice"], function (methodName) {
183.1167 -    ko.observableArray['fn'][methodName] = function () {
183.1168 -        var underlyingArray = this();
183.1169 -        return underlyingArray[methodName].apply(underlyingArray, arguments);
183.1170 -    };
183.1171 -});
183.1172 -
183.1173 -ko.exportSymbol('observableArray', ko.observableArray);
183.1174 -ko.dependentObservable = function (evaluatorFunctionOrOptions, evaluatorFunctionTarget, options) {
183.1175 -    var _latestValue,
183.1176 -        _hasBeenEvaluated = false,
183.1177 -        _isBeingEvaluated = false,
183.1178 -        readFunction = evaluatorFunctionOrOptions;
183.1179 -
183.1180 -    if (readFunction && typeof readFunction == "object") {
183.1181 -        // Single-parameter syntax - everything is on this "options" param
183.1182 -        options = readFunction;
183.1183 -        readFunction = options["read"];
183.1184 -    } else {
183.1185 -        // Multi-parameter syntax - construct the options according to the params passed
183.1186 -        options = options || {};
183.1187 -        if (!readFunction)
183.1188 -            readFunction = options["read"];
183.1189 -    }
183.1190 -    if (typeof readFunction != "function")
183.1191 -        throw new Error("Pass a function that returns the value of the ko.computed");
183.1192 -
183.1193 -    function addSubscriptionToDependency(subscribable) {
183.1194 -        _subscriptionsToDependencies.push(subscribable.subscribe(evaluatePossiblyAsync));
183.1195 -    }
183.1196 -
183.1197 -    function disposeAllSubscriptionsToDependencies() {
183.1198 -        ko.utils.arrayForEach(_subscriptionsToDependencies, function (subscription) {
183.1199 -            subscription.dispose();
183.1200 -        });
183.1201 -        _subscriptionsToDependencies = [];
183.1202 -    }
183.1203 -
183.1204 -    function evaluatePossiblyAsync() {
183.1205 -        var throttleEvaluationTimeout = dependentObservable['throttleEvaluation'];
183.1206 -        if (throttleEvaluationTimeout && throttleEvaluationTimeout >= 0) {
183.1207 -            clearTimeout(evaluationTimeoutInstance);
183.1208 -            evaluationTimeoutInstance = setTimeout(evaluateImmediate, throttleEvaluationTimeout);
183.1209 -        } else
183.1210 -            evaluateImmediate();
183.1211 -    }
183.1212 -
183.1213 -    function evaluateImmediate() {
183.1214 -        if (_isBeingEvaluated) {
183.1215 -            // If the evaluation of a ko.computed causes side effects, it's possible that it will trigger its own re-evaluation.
183.1216 -            // This is not desirable (it's hard for a developer to realise a chain of dependencies might cause this, and they almost
183.1217 -            // certainly didn't intend infinite re-evaluations). So, for predictability, we simply prevent ko.computeds from causing
183.1218 -            // their own re-evaluation. Further discussion at https://github.com/SteveSanderson/knockout/pull/387
183.1219 -            return;
183.1220 -        }
183.1221 -
183.1222 -        // Don't dispose on first evaluation, because the "disposeWhen" callback might
183.1223 -        // e.g., dispose when the associated DOM element isn't in the doc, and it's not
183.1224 -        // going to be in the doc until *after* the first evaluation
183.1225 -        if (_hasBeenEvaluated && disposeWhen()) {
183.1226 -            dispose();
183.1227 -            return;
183.1228 -        }
183.1229 -
183.1230 -        _isBeingEvaluated = true;
183.1231 -        try {
183.1232 -            // Initially, we assume that none of the subscriptions are still being used (i.e., all are candidates for disposal).
183.1233 -            // Then, during evaluation, we cross off any that are in fact still being used.
183.1234 -            var disposalCandidates = ko.utils.arrayMap(_subscriptionsToDependencies, function(item) {return item.target;});
183.1235 -
183.1236 -            ko.dependencyDetection.begin(function(subscribable) {
183.1237 -                var inOld;
183.1238 -                if ((inOld = ko.utils.arrayIndexOf(disposalCandidates, subscribable)) >= 0)
183.1239 -                    disposalCandidates[inOld] = undefined; // Don't want to dispose this subscription, as it's still being used
183.1240 -                else
183.1241 -                    addSubscriptionToDependency(subscribable); // Brand new subscription - add it
183.1242 -            });
183.1243 -
183.1244 -            var newValue = readFunction.call(evaluatorFunctionTarget);
183.1245 -
183.1246 -            // For each subscription no longer being used, remove it from the active subscriptions list and dispose it
183.1247 -            for (var i = disposalCandidates.length - 1; i >= 0; i--) {
183.1248 -                if (disposalCandidates[i])
183.1249 -                    _subscriptionsToDependencies.splice(i, 1)[0].dispose();
183.1250 -            }
183.1251 -            _hasBeenEvaluated = true;
183.1252 -
183.1253 -            dependentObservable["notifySubscribers"](_latestValue, "beforeChange");
183.1254 -            _latestValue = newValue;
183.1255 -            if (DEBUG) dependentObservable._latestValue = _latestValue;
183.1256 -        } finally {
183.1257 -            ko.dependencyDetection.end();
183.1258 -        }
183.1259 -
183.1260 -        dependentObservable["notifySubscribers"](_latestValue);
183.1261 -        _isBeingEvaluated = false;
183.1262 -        if (!_subscriptionsToDependencies.length)
183.1263 -            dispose();
183.1264 -    }
183.1265 -
183.1266 -    function dependentObservable() {
183.1267 -        if (arguments.length > 0) {
183.1268 -            if (typeof writeFunction === "function") {
183.1269 -                // Writing a value
183.1270 -                writeFunction.apply(evaluatorFunctionTarget, arguments);
183.1271 -            } else {
183.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.");
183.1273 -            }
183.1274 -            return this; // Permits chained assignments
183.1275 -        } else {
183.1276 -            // Reading the value
183.1277 -            if (!_hasBeenEvaluated)
183.1278 -                evaluateImmediate();
183.1279 -            ko.dependencyDetection.registerDependency(dependentObservable);
183.1280 -            return _latestValue;
183.1281 -        }
183.1282 -    }
183.1283 -
183.1284 -    function peek() {
183.1285 -        if (!_hasBeenEvaluated)
183.1286 -            evaluateImmediate();
183.1287 -        return _latestValue;
183.1288 -    }
183.1289 -
183.1290 -    function isActive() {
183.1291 -        return !_hasBeenEvaluated || _subscriptionsToDependencies.length > 0;
183.1292 -    }
183.1293 -
183.1294 -    // By here, "options" is always non-null
183.1295 -    var writeFunction = options["write"],
183.1296 -        disposeWhenNodeIsRemoved = options["disposeWhenNodeIsRemoved"] || options.disposeWhenNodeIsRemoved || null,
183.1297 -        disposeWhen = options["disposeWhen"] || options.disposeWhen || function() { return false; },
183.1298 -        dispose = disposeAllSubscriptionsToDependencies,
183.1299 -        _subscriptionsToDependencies = [],
183.1300 -        evaluationTimeoutInstance = null;
183.1301 -
183.1302 -    if (!evaluatorFunctionTarget)
183.1303 -        evaluatorFunctionTarget = options["owner"];
183.1304 -
183.1305 -    dependentObservable.peek = peek;
183.1306 -    dependentObservable.getDependenciesCount = function () { return _subscriptionsToDependencies.length; };
183.1307 -    dependentObservable.hasWriteFunction = typeof options["write"] === "function";
183.1308 -    dependentObservable.dispose = function () { dispose(); };
183.1309 -    dependentObservable.isActive = isActive;
183.1310 -    dependentObservable.valueHasMutated = function() {
183.1311 -        _hasBeenEvaluated = false;
183.1312 -        evaluateImmediate();
183.1313 -    };
183.1314 -
183.1315 -    ko.subscribable.call(dependentObservable);
183.1316 -    ko.utils.extend(dependentObservable, ko.dependentObservable['fn']);
183.1317 -
183.1318 -    ko.exportProperty(dependentObservable, 'peek', dependentObservable.peek);
183.1319 -    ko.exportProperty(dependentObservable, 'dispose', dependentObservable.dispose);
183.1320 -    ko.exportProperty(dependentObservable, 'isActive', dependentObservable.isActive);
183.1321 -    ko.exportProperty(dependentObservable, 'getDependenciesCount', dependentObservable.getDependenciesCount);
183.1322 -
183.1323 -    // Evaluate, unless deferEvaluation is true
183.1324 -    if (options['deferEvaluation'] !== true)
183.1325 -        evaluateImmediate();
183.1326 -
183.1327 -    // Build "disposeWhenNodeIsRemoved" and "disposeWhenNodeIsRemovedCallback" option values.
183.1328 -    // But skip if isActive is false (there will never be any dependencies to dispose).
183.1329 -    // (Note: "disposeWhenNodeIsRemoved" option both proactively disposes as soon as the node is removed using ko.removeNode(),
183.1330 -    // plus adds a "disposeWhen" callback that, on each evaluation, disposes if the node was removed by some other means.)
183.1331 -    if (disposeWhenNodeIsRemoved && isActive()) {
183.1332 -        dispose = function() {
183.1333 -            ko.utils.domNodeDisposal.removeDisposeCallback(disposeWhenNodeIsRemoved, arguments.callee);
183.1334 -            disposeAllSubscriptionsToDependencies();
183.1335 -        };
183.1336 -        ko.utils.domNodeDisposal.addDisposeCallback(disposeWhenNodeIsRemoved, dispose);
183.1337 -        var existingDisposeWhenFunction = disposeWhen;
183.1338 -        disposeWhen = function () {
183.1339 -            return !ko.utils.domNodeIsAttachedToDocument(disposeWhenNodeIsRemoved) || existingDisposeWhenFunction();
183.1340 -        }
183.1341 -    }
183.1342 -
183.1343 -    return dependentObservable;
183.1344 -};
183.1345 -
183.1346 -ko.isComputed = function(instance) {
183.1347 -    return ko.hasPrototype(instance, ko.dependentObservable);
183.1348 -};
183.1349 -
183.1350 -var protoProp = ko.observable.protoProperty; // == "__ko_proto__"
183.1351 -ko.dependentObservable[protoProp] = ko.observable;
183.1352 -
183.1353 -ko.dependentObservable['fn'] = {};
183.1354 -ko.dependentObservable['fn'][protoProp] = ko.dependentObservable;
183.1355 -
183.1356 -ko.exportSymbol('dependentObservable', ko.dependentObservable);
183.1357 -ko.exportSymbol('computed', ko.dependentObservable); // Make "ko.computed" an alias for "ko.dependentObservable"
183.1358 -ko.exportSymbol('isComputed', ko.isComputed);
183.1359 -
183.1360 -(function() {
183.1361 -    var maxNestedObservableDepth = 10; // Escape the (unlikely) pathalogical case where an observable's current value is itself (or similar reference cycle)
183.1362 -
183.1363 -    ko.toJS = function(rootObject) {
183.1364 -        if (arguments.length == 0)
183.1365 -            throw new Error("When calling ko.toJS, pass the object you want to convert.");
183.1366 -
183.1367 -        // We just unwrap everything at every level in the object graph
183.1368 -        return mapJsObjectGraph(rootObject, function(valueToMap) {
183.1369 -            // Loop because an observable's value might in turn be another observable wrapper
183.1370 -            for (var i = 0; ko.isObservable(valueToMap) && (i < maxNestedObservableDepth); i++)
183.1371 -                valueToMap = valueToMap();
183.1372 -            return valueToMap;
183.1373 -        });
183.1374 -    };
183.1375 -
183.1376 -    ko.toJSON = function(rootObject, replacer, space) {     // replacer and space are optional
183.1377 -        var plainJavaScriptObject = ko.toJS(rootObject);
183.1378 -        return ko.utils.stringifyJson(plainJavaScriptObject, replacer, space);
183.1379 -    };
183.1380 -
183.1381 -    function mapJsObjectGraph(rootObject, mapInputCallback, visitedObjects) {
183.1382 -        visitedObjects = visitedObjects || new objectLookup();
183.1383 -
183.1384 -        rootObject = mapInputCallback(rootObject);
183.1385 -        var canHaveProperties = (typeof rootObject == "object") && (rootObject !== null) && (rootObject !== undefined) && (!(rootObject instanceof Date));
183.1386 -        if (!canHaveProperties)
183.1387 -            return rootObject;
183.1388 -
183.1389 -        var outputProperties = rootObject instanceof Array ? [] : {};
183.1390 -        visitedObjects.save(rootObject, outputProperties);
183.1391 -
183.1392 -        visitPropertiesOrArrayEntries(rootObject, function(indexer) {
183.1393 -            var propertyValue = mapInputCallback(rootObject[indexer]);
183.1394 -
183.1395 -            switch (typeof propertyValue) {
183.1396 -                case "boolean":
183.1397 -                case "number":
183.1398 -                case "string":
183.1399 -                case "function":
183.1400 -                    outputProperties[indexer] = propertyValue;
183.1401 -                    break;
183.1402 -                case "object":
183.1403 -                case "undefined":
183.1404 -                    var previouslyMappedValue = visitedObjects.get(propertyValue);
183.1405 -                    outputProperties[indexer] = (previouslyMappedValue !== undefined)
183.1406 -                        ? previouslyMappedValue
183.1407 -                        : mapJsObjectGraph(propertyValue, mapInputCallback, visitedObjects);
183.1408 -                    break;
183.1409 -            }
183.1410 -        });
183.1411 -
183.1412 -        return outputProperties;
183.1413 -    }
183.1414 -
183.1415 -    function visitPropertiesOrArrayEntries(rootObject, visitorCallback) {
183.1416 -        if (rootObject instanceof Array) {
183.1417 -            for (var i = 0; i < rootObject.length; i++)
183.1418 -                visitorCallback(i);
183.1419 -
183.1420 -            // For arrays, also respect toJSON property for custom mappings (fixes #278)
183.1421 -            if (typeof rootObject['toJSON'] == 'function')
183.1422 -                visitorCallback('toJSON');
183.1423 -        } else {
183.1424 -            for (var propertyName in rootObject)
183.1425 -                visitorCallback(propertyName);
183.1426 -        }
183.1427 -    };
183.1428 -
183.1429 -    function objectLookup() {
183.1430 -        var keys = [];
183.1431 -        var values = [];
183.1432 -        this.save = function(key, value) {
183.1433 -            var existingIndex = ko.utils.arrayIndexOf(keys, key);
183.1434 -            if (existingIndex >= 0)
183.1435 -                values[existingIndex] = value;
183.1436 -            else {
183.1437 -                keys.push(key);
183.1438 -                values.push(value);
183.1439 -            }
183.1440 -        };
183.1441 -        this.get = function(key) {
183.1442 -            var existingIndex = ko.utils.arrayIndexOf(keys, key);
183.1443 -            return (existingIndex >= 0) ? values[existingIndex] : undefined;
183.1444 -        };
183.1445 -    };
183.1446 -})();
183.1447 -
183.1448 -ko.exportSymbol('toJS', ko.toJS);
183.1449 -ko.exportSymbol('toJSON', ko.toJSON);
183.1450 -(function () {
183.1451 -    var hasDomDataExpandoProperty = '__ko__hasDomDataOptionValue__';
183.1452 -
183.1453 -    // Normally, SELECT elements and their OPTIONs can only take value of type 'string' (because the values
183.1454 -    // are stored on DOM attributes). ko.selectExtensions provides a way for SELECTs/OPTIONs to have values
183.1455 -    // that are arbitrary objects. This is very convenient when implementing things like cascading dropdowns.
183.1456 -    ko.selectExtensions = {
183.1457 -        readValue : function(element) {
183.1458 -            switch (ko.utils.tagNameLower(element)) {
183.1459 -                case 'option':
183.1460 -                    if (element[hasDomDataExpandoProperty] === true)
183.1461 -                        return ko.utils.domData.get(element, ko.bindingHandlers.options.optionValueDomDataKey);
183.1462 -                    return ko.utils.ieVersion <= 7
183.1463 -                        ? (element.getAttributeNode('value').specified ? element.value : element.text)
183.1464 -                        : element.value;
183.1465 -                case 'select':
183.1466 -                    return element.selectedIndex >= 0 ? ko.selectExtensions.readValue(element.options[element.selectedIndex]) : undefined;
183.1467 -                default:
183.1468 -                    return element.value;
183.1469 -            }
183.1470 -        },
183.1471 -
183.1472 -        writeValue: function(element, value) {
183.1473 -            switch (ko.utils.tagNameLower(element)) {
183.1474 -                case 'option':
183.1475 -                    switch(typeof value) {
183.1476 -                        case "string":
183.1477 -                            ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, undefined);
183.1478 -                            if (hasDomDataExpandoProperty in element) { // IE <= 8 throws errors if you delete non-existent properties from a DOM node
183.1479 -                                delete element[hasDomDataExpandoProperty];
183.1480 -                            }
183.1481 -                            element.value = value;
183.1482 -                            break;
183.1483 -                        default:
183.1484 -                            // Store arbitrary object using DomData
183.1485 -                            ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, value);
183.1486 -                            element[hasDomDataExpandoProperty] = true;
183.1487 -
183.1488 -                            // Special treatment of numbers is just for backward compatibility. KO 1.2.1 wrote numerical values to element.value.
183.1489 -                            element.value = typeof value === "number" ? value : "";
183.1490 -                            break;
183.1491 -                    }
183.1492 -                    break;
183.1493 -                case 'select':
183.1494 -                    for (var i = element.options.length - 1; i >= 0; i--) {
183.1495 -                        if (ko.selectExtensions.readValue(element.options[i]) == value) {
183.1496 -                            element.selectedIndex = i;
183.1497 -                            break;
183.1498 -                        }
183.1499 -                    }
183.1500 -                    break;
183.1501 -                default:
183.1502 -                    if ((value === null) || (value === undefined))
183.1503 -                        value = "";
183.1504 -                    element.value = value;
183.1505 -                    break;
183.1506 -            }
183.1507 -        }
183.1508 -    };
183.1509 -})();
183.1510 -
183.1511 -ko.exportSymbol('selectExtensions', ko.selectExtensions);
183.1512 -ko.exportSymbol('selectExtensions.readValue', ko.selectExtensions.readValue);
183.1513 -ko.exportSymbol('selectExtensions.writeValue', ko.selectExtensions.writeValue);
183.1514 -ko.expressionRewriting = (function () {
183.1515 -    var restoreCapturedTokensRegex = /\@ko_token_(\d+)\@/g;
183.1516 -    var javaScriptReservedWords = ["true", "false"];
183.1517 -
183.1518 -    // Matches something that can be assigned to--either an isolated identifier or something ending with a property accessor
183.1519 -    // This is designed to be simple and avoid false negatives, but could produce false positives (e.g., a+b.c).
183.1520 -    var javaScriptAssignmentTarget = /^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i;
183.1521 -
183.1522 -    function restoreTokens(string, tokens) {
183.1523 -        var prevValue = null;
183.1524 -        while (string != prevValue) { // Keep restoring tokens until it no longer makes a difference (they may be nested)
183.1525 -            prevValue = string;
183.1526 -            string = string.replace(restoreCapturedTokensRegex, function (match, tokenIndex) {
183.1527 -                return tokens[tokenIndex];
183.1528 -            });
183.1529 -        }
183.1530 -        return string;
183.1531 -    }
183.1532 -
183.1533 -    function getWriteableValue(expression) {
183.1534 -        if (ko.utils.arrayIndexOf(javaScriptReservedWords, ko.utils.stringTrim(expression).toLowerCase()) >= 0)
183.1535 -            return false;
183.1536 -        var match = expression.match(javaScriptAssignmentTarget);
183.1537 -        return match === null ? false : match[1] ? ('Object(' + match[1] + ')' + match[2]) : expression;
183.1538 -    }
183.1539 -
183.1540 -    function ensureQuoted(key) {
183.1541 -        var trimmedKey = ko.utils.stringTrim(key);
183.1542 -        switch (trimmedKey.length && trimmedKey.charAt(0)) {
183.1543 -            case "'":
183.1544 -            case '"':
183.1545 -                return key;
183.1546 -            default:
183.1547 -                return "'" + trimmedKey + "'";
183.1548 -        }
183.1549 -    }
183.1550 -
183.1551 -    return {
183.1552 -        bindingRewriteValidators: [],
183.1553 -
183.1554 -        parseObjectLiteral: function(objectLiteralString) {
183.1555 -            // A full tokeniser+lexer would add too much weight to this library, so here's a simple parser
183.1556 -            // that is sufficient just to split an object literal string into a set of top-level key-value pairs
183.1557 -
183.1558 -            var str = ko.utils.stringTrim(objectLiteralString);
183.1559 -            if (str.length < 3)
183.1560 -                return [];
183.1561 -            if (str.charAt(0) === "{")// Ignore any braces surrounding the whole object literal
183.1562 -                str = str.substring(1, str.length - 1);
183.1563 -
183.1564 -            // Pull out any string literals and regex literals
183.1565 -            var tokens = [];
183.1566 -            var tokenStart = null, tokenEndChar;
183.1567 -            for (var position = 0; position < str.length; position++) {
183.1568 -                var c = str.charAt(position);
183.1569 -                if (tokenStart === null) {
183.1570 -                    switch (c) {
183.1571 -                        case '"':
183.1572 -                        case "'":
183.1573 -                        case "/":
183.1574 -                            tokenStart = position;
183.1575 -                            tokenEndChar = c;
183.1576 -                            break;
183.1577 -                    }
183.1578 -                } else if ((c == tokenEndChar) && (str.charAt(position - 1) !== "\\")) {
183.1579 -                    var token = str.substring(tokenStart, position + 1);
183.1580 -                    tokens.push(token);
183.1581 -                    var replacement = "@ko_token_" + (tokens.length - 1) + "@";
183.1582 -                    str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
183.1583 -                    position -= (token.length - replacement.length);
183.1584 -                    tokenStart = null;
183.1585 -                }
183.1586 -            }
183.1587 -
183.1588 -            // Next pull out balanced paren, brace, and bracket blocks
183.1589 -            tokenStart = null;
183.1590 -            tokenEndChar = null;
183.1591 -            var tokenDepth = 0, tokenStartChar = null;
183.1592 -            for (var position = 0; position < str.length; position++) {
183.1593 -                var c = str.charAt(position);
183.1594 -                if (tokenStart === null) {
183.1595 -                    switch (c) {
183.1596 -                        case "{": tokenStart = position; tokenStartChar = c;
183.1597 -                                  tokenEndChar = "}";
183.1598 -                                  break;
183.1599 -                        case "(": tokenStart = position; tokenStartChar = c;
183.1600 -                                  tokenEndChar = ")";
183.1601 -                                  break;
183.1602 -                        case "[": tokenStart = position; tokenStartChar = c;
183.1603 -                                  tokenEndChar = "]";
183.1604 -                                  break;
183.1605 -                    }
183.1606 -                }
183.1607 -
183.1608 -                if (c === tokenStartChar)
183.1609 -                    tokenDepth++;
183.1610 -                else if (c === tokenEndChar) {
183.1611 -                    tokenDepth--;
183.1612 -                    if (tokenDepth === 0) {
183.1613 -                        var token = str.substring(tokenStart, position + 1);
183.1614 -                        tokens.push(token);
183.1615 -                        var replacement = "@ko_token_" + (tokens.length - 1) + "@";
183.1616 -                        str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
183.1617 -                        position -= (token.length - replacement.length);
183.1618 -                        tokenStart = null;
183.1619 -                    }
183.1620 -                }
183.1621 -            }
183.1622 -
183.1623 -            // Now we can safely split on commas to get the key/value pairs
183.1624 -            var result = [];
183.1625 -            var keyValuePairs = str.split(",");
183.1626 -            for (var i = 0, j = keyValuePairs.length; i < j; i++) {
183.1627 -                var pair = keyValuePairs[i];
183.1628 -                var colonPos = pair.indexOf(":");
183.1629 -                if ((colonPos > 0) && (colonPos < pair.length - 1)) {
183.1630 -                    var key = pair.substring(0, colonPos);
183.1631 -                    var value = pair.substring(colonPos + 1);
183.1632 -                    result.push({ 'key': restoreTokens(key, tokens), 'value': restoreTokens(value, tokens) });
183.1633 -                } else {
183.1634 -                    result.push({ 'unknown': restoreTokens(pair, tokens) });
183.1635 -                }
183.1636 -            }
183.1637 -            return result;
183.1638 -        },
183.1639 -
183.1640 -        preProcessBindings: function (objectLiteralStringOrKeyValueArray) {
183.1641 -            var keyValueArray = typeof objectLiteralStringOrKeyValueArray === "string"
183.1642 -                ? ko.expressionRewriting.parseObjectLiteral(objectLiteralStringOrKeyValueArray)
183.1643 -                : objectLiteralStringOrKeyValueArray;
183.1644 -            var resultStrings = [], propertyAccessorResultStrings = [];
183.1645 -
183.1646 -            var keyValueEntry;
183.1647 -            for (var i = 0; keyValueEntry = keyValueArray[i]; i++) {
183.1648 -                if (resultStrings.length > 0)
183.1649 -                    resultStrings.push(",");
183.1650 -
183.1651 -                if (keyValueEntry['key']) {
183.1652 -                    var quotedKey = ensureQuoted(keyValueEntry['key']), val = keyValueEntry['value'];
183.1653 -                    resultStrings.push(quotedKey);
183.1654 -                    resultStrings.push(":");
183.1655 -                    resultStrings.push(val);
183.1656 -
183.1657 -                    if (val = getWriteableValue(ko.utils.stringTrim(val))) {
183.1658 -                        if (propertyAccessorResultStrings.length > 0)
183.1659 -                            propertyAccessorResultStrings.push(", ");
183.1660 -                        propertyAccessorResultStrings.push(quotedKey + " : function(__ko_value) { " + val + " = __ko_value; }");
183.1661 -                    }
183.1662 -                } else if (keyValueEntry['unknown']) {
183.1663 -                    resultStrings.push(keyValueEntry['unknown']);
183.1664 -                }
183.1665 -            }
183.1666 -
183.1667 -            var combinedResult = resultStrings.join("");
183.1668 -            if (propertyAccessorResultStrings.length > 0) {
183.1669 -                var allPropertyAccessors = propertyAccessorResultStrings.join("");
183.1670 -                combinedResult = combinedResult + ", '_ko_property_writers' : { " + allPropertyAccessors + " } ";
183.1671 -            }
183.1672 -
183.1673 -            return combinedResult;
183.1674 -        },
183.1675 -
183.1676 -        keyValueArrayContainsKey: function(keyValueArray, key) {
183.1677 -            for (var i = 0; i < keyValueArray.length; i++)
183.1678 -                if (ko.utils.stringTrim(keyValueArray[i]['key']) == key)
183.1679 -                    return true;
183.1680 -            return false;
183.1681 -        },
183.1682 -
183.1683 -        // Internal, private KO utility for updating model properties from within bindings
183.1684 -        // property:            If the property being updated is (or might be) an observable, pass it here
183.1685 -        //                      If it turns out to be a writable observable, it will be written to directly
183.1686 -        // allBindingsAccessor: All bindings in the current execution context.
183.1687 -        //                      This will be searched for a '_ko_property_writers' property in case you're writing to a non-observable
183.1688 -        // key:                 The key identifying the property to be written. Example: for { hasFocus: myValue }, write to 'myValue' by specifying the key 'hasFocus'
183.1689 -        // value:               The value to be written
183.1690 -        // checkIfDifferent:    If true, and if the property being written is a writable observable, the value will only be written if
183.1691 -        //                      it is !== existing value on that writable observable
183.1692 -        writeValueToProperty: function(property, allBindingsAccessor, key, value, checkIfDifferent) {
183.1693 -            if (!property || !ko.isWriteableObservable(property)) {
183.1694 -                var propWriters = allBindingsAccessor()['_ko_property_writers'];
183.1695 -                if (propWriters && propWriters[key])
183.1696 -                    propWriters[key](value);
183.1697 -            } else if (!checkIfDifferent || property.peek() !== value) {
183.1698 -                property(value);
183.1699 -            }
183.1700 -        }
183.1701 -    };
183.1702 -})();
183.1703 -
183.1704 -ko.exportSymbol('expressionRewriting', ko.expressionRewriting);
183.1705 -ko.exportSymbol('expressionRewriting.bindingRewriteValidators', ko.expressionRewriting.bindingRewriteValidators);
183.1706 -ko.exportSymbol('expressionRewriting.parseObjectLiteral', ko.expressionRewriting.parseObjectLiteral);
183.1707 -ko.exportSymbol('expressionRewriting.preProcessBindings', ko.expressionRewriting.preProcessBindings);
183.1708 -
183.1709 -// For backward compatibility, define the following aliases. (Previously, these function names were misleading because
183.1710 -// they referred to JSON specifically, even though they actually work with arbitrary JavaScript object literal expressions.)
183.1711 -ko.exportSymbol('jsonExpressionRewriting', ko.expressionRewriting);
183.1712 -ko.exportSymbol('jsonExpressionRewriting.insertPropertyAccessorsIntoJson', ko.expressionRewriting.preProcessBindings);(function() {
183.1713 -    // "Virtual elements" is an abstraction on top of the usual DOM API which understands the notion that comment nodes
183.1714 -    // may be used to represent hierarchy (in addition to the DOM's natural hierarchy).
183.1715 -    // If you call the DOM-manipulating functions on ko.virtualElements, you will be able to read and write the state
183.1716 -    // of that virtual hierarchy
183.1717 -    //
183.1718 -    // The point of all this is to support containerless templates (e.g., <!-- ko foreach:someCollection -->blah<!-- /ko -->)
183.1719 -    // without having to scatter special cases all over the binding and templating code.
183.1720 -
183.1721 -    // IE 9 cannot reliably read the "nodeValue" property of a comment node (see https://github.com/SteveSanderson/knockout/issues/186)
183.1722 -    // but it does give them a nonstandard alternative property called "text" that it can read reliably. Other browsers don't have that property.
183.1723 -    // So, use node.text where available, and node.nodeValue elsewhere
183.1724 -    var commentNodesHaveTextProperty = document.createComment("test").text === "<!--test-->";
183.1725 -
183.1726 -    var startCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*-->$/ : /^\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*$/;
183.1727 -    var endCommentRegex =   commentNodesHaveTextProperty ? /^<!--\s*\/ko\s*-->$/ : /^\s*\/ko\s*$/;
183.1728 -    var htmlTagsWithOptionallyClosingChildren = { 'ul': true, 'ol': true };
183.1729 -
183.1730 -    function isStartComment(node) {
183.1731 -        return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(startCommentRegex);
183.1732 -    }
183.1733 -
183.1734 -    function isEndComment(node) {
183.1735 -        return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(endCommentRegex);
183.1736 -    }
183.1737 -
183.1738 -    function getVirtualChildren(startComment, allowUnbalanced) {
183.1739 -        var currentNode = startComment;
183.1740 -        var depth = 1;
183.1741 -        var children = [];
183.1742 -        while (currentNode = currentNode.nextSibling) {
183.1743 -            if (isEndComment(currentNode)) {
183.1744 -                depth--;
183.1745 -                if (depth === 0)
183.1746 -                    return children;
183.1747 -            }
183.1748 -
183.1749 -            children.push(currentNode);
183.1750 -
183.1751 -            if (isStartComment(currentNode))
183.1752 -                depth++;
183.1753 -        }
183.1754 -        if (!allowUnbalanced)
183.1755 -            throw new Error("Cannot find closing comment tag to match: " + startComment.nodeValue);
183.1756 -        return null;
183.1757 -    }
183.1758 -
183.1759 -    function getMatchingEndComment(startComment, allowUnbalanced) {
183.1760 -        var allVirtualChildren = getVirtualChildren(startComment, allowUnbalanced);
183.1761 -        if (allVirtualChildren) {
183.1762 -            if (allVirtualChildren.length > 0)
183.1763 -                return allVirtualChildren[allVirtualChildren.length - 1].nextSibling;
183.1764 -            return startComment.nextSibling;
183.1765 -        } else
183.1766 -            return null; // Must have no matching end comment, and allowUnbalanced is true
183.1767 -    }
183.1768 -
183.1769 -    function getUnbalancedChildTags(node) {
183.1770 -        // e.g., from <div>OK</div><!-- ko blah --><span>Another</span>, returns: <!-- ko blah --><span>Another</span>
183.1771 -        //       from <div>OK</div><!-- /ko --><!-- /ko -->,             returns: <!-- /ko --><!-- /ko -->
183.1772 -        var childNode = node.firstChild, captureRemaining = null;
183.1773 -        if (childNode) {
183.1774 -            do {
183.1775 -                if (captureRemaining)                   // We already hit an unbalanced node and are now just scooping up all subsequent nodes
183.1776 -                    captureRemaining.push(childNode);
183.1777 -                else if (isStartComment(childNode)) {
183.1778 -                    var matchingEndComment = getMatchingEndComment(childNode, /* allowUnbalanced: */ true);
183.1779 -                    if (matchingEndComment)             // It's a balanced tag, so skip immediately to the end of this virtual set
183.1780 -                        childNode = matchingEndComment;
183.1781 -                    else
183.1782 -                        captureRemaining = [childNode]; // It's unbalanced, so start capturing from this point
183.1783 -                } else if (isEndComment(childNode)) {
183.1784 -                    captureRemaining = [childNode];     // It's unbalanced (if it wasn't, we'd have skipped over it already), so start capturing
183.1785 -                }
183.1786 -            } while (childNode = childNode.nextSibling);
183.1787 -        }
183.1788 -        return captureRemaining;
183.1789 -    }
183.1790 -
183.1791 -    ko.virtualElements = {
183.1792 -        allowedBindings: {},
183.1793 -
183.1794 -        childNodes: function(node) {
183.1795 -            return isStartComment(node) ? getVirtualChildren(node) : node.childNodes;
183.1796 -        },
183.1797 -
183.1798 -        emptyNode: function(node) {
183.1799 -            if (!isStartComment(node))
183.1800 -                ko.utils.emptyDomNode(node);
183.1801 -            else {
183.1802 -                var virtualChildren = ko.virtualElements.childNodes(node);
183.1803 -                for (var i = 0, j = virtualChildren.length; i < j; i++)
183.1804 -                    ko.removeNode(virtualChildren[i]);
183.1805 -            }
183.1806 -        },
183.1807 -
183.1808 -        setDomNodeChildren: function(node, childNodes) {
183.1809 -            if (!isStartComment(node))
183.1810 -                ko.utils.setDomNodeChildren(node, childNodes);
183.1811 -            else {
183.1812 -                ko.virtualElements.emptyNode(node);
183.1813 -                var endCommentNode = node.nextSibling; // Must be the next sibling, as we just emptied the children
183.1814 -                for (var i = 0, j = childNodes.length; i < j; i++)
183.1815 -                    endCommentNode.parentNode.insertBefore(childNodes[i], endCommentNode);
183.1816 -            }
183.1817 -        },
183.1818 -
183.1819 -        prepend: function(containerNode, nodeToPrepend) {
183.1820 -            if (!isStartComment(containerNode)) {
183.1821 -                if (containerNode.firstChild)
183.1822 -                    containerNode.insertBefore(nodeToPrepend, containerNode.firstChild);
183.1823 -                else
183.1824 -                    containerNode.appendChild(nodeToPrepend);
183.1825 -            } else {
183.1826 -                // Start comments must always have a parent and at least one following sibling (the end comment)
183.1827 -                containerNode.parentNode.insertBefore(nodeToPrepend, containerNode.nextSibling);
183.1828 -            }
183.1829 -        },
183.1830 -
183.1831 -        insertAfter: function(containerNode, nodeToInsert, insertAfterNode) {
183.1832 -            if (!insertAfterNode) {
183.1833 -                ko.virtualElements.prepend(containerNode, nodeToInsert);
183.1834 -            } else if (!isStartComment(containerNode)) {
183.1835 -                // Insert after insertion point
183.1836 -                if (insertAfterNode.nextSibling)
183.1837 -                    containerNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
183.1838 -                else
183.1839 -                    containerNode.appendChild(nodeToInsert);
183.1840 -            } else {
183.1841 -                // Children of start comments must always have a parent and at least one following sibling (the end comment)
183.1842 -                containerNode.parentNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
183.1843 -            }
183.1844 -        },
183.1845 -
183.1846 -        firstChild: function(node) {
183.1847 -            if (!isStartComment(node))
183.1848 -                return node.firstChild;
183.1849 -            if (!node.nextSibling || isEndComment(node.nextSibling))
183.1850 -                return null;
183.1851 -            return node.nextSibling;
183.1852 -        },
183.1853 -
183.1854 -        nextSibling: function(node) {
183.1855 -            if (isStartComment(node))
183.1856 -                node = getMatchingEndComment(node);
183.1857 -            if (node.nextSibling && isEndComment(node.nextSibling))
183.1858 -                return null;
183.1859 -            return node.nextSibling;
183.1860 -        },
183.1861 -
183.1862 -        virtualNodeBindingValue: function(node) {
183.1863 -            var regexMatch = isStartComment(node);
183.1864 -            return regexMatch ? regexMatch[1] : null;
183.1865 -        },
183.1866 -
183.1867 -        normaliseVirtualElementDomStructure: function(elementVerified) {
183.1868 -            // Workaround for https://github.com/SteveSanderson/knockout/issues/155
183.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
183.1870 -            // that are direct descendants of <ul> into the preceding <li>)
183.1871 -            if (!htmlTagsWithOptionallyClosingChildren[ko.utils.tagNameLower(elementVerified)])
183.1872 -                return;
183.1873 -
183.1874 -            // Scan immediate children to see if they contain unbalanced comment tags. If they do, those comment tags
183.1875 -            // must be intended to appear *after* that child, so move them there.
183.1876 -            var childNode = elementVerified.firstChild;
183.1877 -            if (childNode) {
183.1878 -                do {
183.1879 -                    if (childNode.nodeType === 1) {
183.1880 -                        var unbalancedTags = getUnbalancedChildTags(childNode);
183.1881 -                        if (unbalancedTags) {
183.1882 -                            // Fix up the DOM by moving the unbalanced tags to where they most likely were intended to be placed - *after* the child
183.1883 -                            var nodeToInsertBefore = childNode.nextSibling;
183.1884 -                            for (var i = 0; i < unbalancedTags.length; i++) {
183.1885 -                                if (nodeToInsertBefore)
183.1886 -                                    elementVerified.insertBefore(unbalancedTags[i], nodeToInsertBefore);
183.1887 -                                else
183.1888 -                                    elementVerified.appendChild(unbalancedTags[i]);
183.1889 -                            }
183.1890 -                        }
183.1891 -                    }
183.1892 -                } while (childNode = childNode.nextSibling);
183.1893 -            }
183.1894 -        }
183.1895 -    };
183.1896 -})();
183.1897 -ko.exportSymbol('virtualElements', ko.virtualElements);
183.1898 -ko.exportSymbol('virtualElements.allowedBindings', ko.virtualElements.allowedBindings);
183.1899 -ko.exportSymbol('virtualElements.emptyNode', ko.virtualElements.emptyNode);
183.1900 -//ko.exportSymbol('virtualElements.firstChild', ko.virtualElements.firstChild);     // firstChild is not minified
183.1901 -ko.exportSymbol('virtualElements.insertAfter', ko.virtualElements.insertAfter);
183.1902 -//ko.exportSymbol('virtualElements.nextSibling', ko.virtualElements.nextSibling);   // nextSibling is not minified
183.1903 -ko.exportSymbol('virtualElements.prepend', ko.virtualElements.prepend);
183.1904 -ko.exportSymbol('virtualElements.setDomNodeChildren', ko.virtualElements.setDomNodeChildren);
183.1905 -(function() {
183.1906 -    var defaultBindingAttributeName = "data-bind";
183.1907 -
183.1908 -    ko.bindingProvider = function() {
183.1909 -        this.bindingCache = {};
183.1910 -    };
183.1911 -
183.1912 -    ko.utils.extend(ko.bindingProvider.prototype, {
183.1913 -        'nodeHasBindings': function(node) {
183.1914 -            switch (node.nodeType) {
183.1915 -                case 1: return node.getAttribute(defaultBindingAttributeName) != null;   // Element
183.1916 -                case 8: return ko.virtualElements.virtualNodeBindingValue(node) != null; // Comment node
183.1917 -                default: return false;
183.1918 -            }
183.1919 -        },
183.1920 -
183.1921 -        'getBindings': function(node, bindingContext) {
183.1922 -            var bindingsString = this['getBindingsString'](node, bindingContext);
183.1923 -            return bindingsString ? this['parseBindingsString'](bindingsString, bindingContext, node) : null;
183.1924 -        },
183.1925 -
183.1926 -        // The following function is only used internally by this default provider.
183.1927 -        // It's not part of the interface definition for a general binding provider.
183.1928 -        'getBindingsString': function(node, bindingContext) {
183.1929 -            switch (node.nodeType) {
183.1930 -                case 1: return node.getAttribute(defaultBindingAttributeName);   // Element
183.1931 -                case 8: return ko.virtualElements.virtualNodeBindingValue(node); // Comment node
183.1932 -                default: return null;
183.1933 -            }
183.1934 -        },
183.1935 -
183.1936 -        // The following function is only used internally by this default provider.
183.1937 -        // It's not part of the interface definition for a general binding provider.
183.1938 -        'parseBindingsString': function(bindingsString, bindingContext, node) {
183.1939 -            try {
183.1940 -                var bindingFunction = createBindingsStringEvaluatorViaCache(bindingsString, this.bindingCache);
183.1941 -                return bindingFunction(bindingContext, node);
183.1942 -            } catch (ex) {
183.1943 -                throw new Error("Unable to parse bindings.\nMessage: " + ex + ";\nBindings value: " + bindingsString);
183.1944 -            }
183.1945 -        }
183.1946 -    });
183.1947 -
183.1948 -    ko.bindingProvider['instance'] = new ko.bindingProvider();
183.1949 -
183.1950 -    function createBindingsStringEvaluatorViaCache(bindingsString, cache) {
183.1951 -        var cacheKey = bindingsString;
183.1952 -        return cache[cacheKey]
183.1953 -            || (cache[cacheKey] = createBindingsStringEvaluator(bindingsString));
183.1954 -    }
183.1955 -
183.1956 -    function createBindingsStringEvaluator(bindingsString) {
183.1957 -        // Build the source for a function that evaluates "expression"
183.1958 -        // For each scope variable, add an extra level of "with" nesting
183.1959 -        // Example result: with(sc1) { with(sc0) { return (expression) } }
183.1960 -        var rewrittenBindings = ko.expressionRewriting.preProcessBindings(bindingsString),
183.1961 -            functionBody = "with($context){with($data||{}){return{" + rewrittenBindings + "}}}";
183.1962 -        return new Function("$context", "$element", functionBody);
183.1963 -    }
183.1964 -})();
183.1965 -
183.1966 -ko.exportSymbol('bindingProvider', ko.bindingProvider);
183.1967 -(function () {
183.1968 -    ko.bindingHandlers = {};
183.1969 -
183.1970 -    ko.bindingContext = function(dataItem, parentBindingContext, dataItemAlias) {
183.1971 -        if (parentBindingContext) {
183.1972 -            ko.utils.extend(this, parentBindingContext); // Inherit $root and any custom properties
183.1973 -            this['$parentContext'] = parentBindingContext;
183.1974 -            this['$parent'] = parentBindingContext['$data'];
183.1975 -            this['$parents'] = (parentBindingContext['$parents'] || []).slice(0);
183.1976 -            this['$parents'].unshift(this['$parent']);
183.1977 -        } else {
183.1978 -            this['$parents'] = [];
183.1979 -            this['$root'] = dataItem;
183.1980 -            // Export 'ko' in the binding context so it will be available in bindings and templates
183.1981 -            // even if 'ko' isn't exported as a global, such as when using an AMD loader.
183.1982 -            // See https://github.com/SteveSanderson/knockout/issues/490
183.1983 -            this['ko'] = ko;
183.1984 -        }
183.1985 -        this['$data'] = dataItem;
183.1986 -        if (dataItemAlias)
183.1987 -            this[dataItemAlias] = dataItem;
183.1988 -    }
183.1989 -    ko.bindingContext.prototype['createChildContext'] = function (dataItem, dataItemAlias) {
183.1990 -        return new ko.bindingContext(dataItem, this, dataItemAlias);
183.1991 -    };
183.1992 -    ko.bindingContext.prototype['extend'] = function(properties) {
183.1993 -        var clone = ko.utils.extend(new ko.bindingContext(), this);
183.1994 -        return ko.utils.extend(clone, properties);
183.1995 -    };
183.1996 -
183.1997 -    function validateThatBindingIsAllowedForVirtualElements(bindingName) {
183.1998 -        var validator = ko.virtualElements.allowedBindings[bindingName];
183.1999 -        if (!validator)
183.2000 -            throw new Error("The binding '" + bindingName + "' cannot be used with virtual elements")
183.2001 -    }
183.2002 -
183.2003 -    function applyBindingsToDescendantsInternal (viewModel, elementOrVirtualElement, bindingContextsMayDifferFromDomParentElement) {
183.2004 -        var currentChild, nextInQueue = ko.virtualElements.firstChild(elementOrVirtualElement);
183.2005 -        while (currentChild = nextInQueue) {
183.2006 -            // Keep a record of the next child *before* applying bindings, in case the binding removes the current child from its position
183.2007 -            nextInQueue = ko.virtualElements.nextSibling(currentChild);
183.2008 -            applyBindingsToNodeAndDescendantsInternal(viewModel, currentChild, bindingContextsMayDifferFromDomParentElement);
183.2009 -        }
183.2010 -    }
183.2011 -
183.2012 -    function applyBindingsToNodeAndDescendantsInternal (viewModel, nodeVerified, bindingContextMayDifferFromDomParentElement) {
183.2013 -        var shouldBindDescendants = true;
183.2014 -
183.2015 -        // Perf optimisation: Apply bindings only if...
183.2016 -        // (1) We need to store the binding context on this node (because it may differ from the DOM parent node's binding context)
183.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
183.2018 -        // (2) It might have bindings (e.g., it has a data-bind attribute, or it's a marker for a containerless template)
183.2019 -        var isElement = (nodeVerified.nodeType === 1);
183.2020 -        if (isElement) // Workaround IE <= 8 HTML parsing weirdness
183.2021 -            ko.virtualElements.normaliseVirtualElementDomStructure(nodeVerified);
183.2022 -
183.2023 -        var shouldApplyBindings = (isElement && bindingContextMayDifferFromDomParentElement)             // Case (1)
183.2024 -                               || ko.bindingProvider['instance']['nodeHasBindings'](nodeVerified);       // Case (2)
183.2025 -        if (shouldApplyBindings)
183.2026 -            shouldBindDescendants = applyBindingsToNodeInternal(nodeVerified, null, viewModel, bindingContextMayDifferFromDomParentElement).shouldBindDescendants;
183.2027 -
183.2028 -        if (shouldBindDescendants) {
183.2029 -            // We're recursing automatically into (real or virtual) child nodes without changing binding contexts. So,
183.2030 -            //  * For children of a *real* element, the binding context is certainly the same as on their DOM .parentNode,
183.2031 -            //    hence bindingContextsMayDifferFromDomParentElement is false
183.2032 -            //  * For children of a *virtual* element, we can't be sure. Evaluating .parentNode on those children may
183.2033 -            //    skip over any number of intermediate virtual elements, any of which might define a custom binding context,
183.2034 -            //    hence bindingContextsMayDifferFromDomParentElement is true
183.2035 -            applyBindingsToDescendantsInternal(viewModel, nodeVerified, /* bindingContextsMayDifferFromDomParentElement: */ !isElement);
183.2036 -        }
183.2037 -    }
183.2038 -
183.2039 -    function applyBindingsToNodeInternal (node, bindings, viewModelOrBindingContext, bindingContextMayDifferFromDomParentElement) {
183.2040 -        // Need to be sure that inits are only run once, and updates never run until all the inits have been run
183.2041 -        var initPhase = 0; // 0 = before all inits, 1 = during inits, 2 = after all inits
183.2042 -
183.2043 -        // Each time the dependentObservable is evaluated (after data changes),
183.2044 -        // the binding attribute is reparsed so that it can pick out the correct
183.2045 -        // model properties in the context of the changed data.
183.2046 -        // DOM event callbacks need to be able to access this changed data,
183.2047 -        // so we need a single parsedBindings variable (shared by all callbacks
183.2048 -        // associated with this node's bindings) that all the closures can access.
183.2049 -        var parsedBindings;
183.2050 -        function makeValueAccessor(bindingKey) {
183.2051 -            return function () { return parsedBindings[bindingKey] }
183.2052 -        }
183.2053 -        function parsedBindingsAccessor() {
183.2054 -            return parsedBindings;
183.2055 -        }
183.2056 -
183.2057 -        var bindingHandlerThatControlsDescendantBindings;
183.2058 -        ko.dependentObservable(
183.2059 -            function () {
183.2060 -                // Ensure we have a nonnull binding context to work with
183.2061 -                var bindingContextInstance = viewModelOrBindingContext && (viewModelOrBindingContext instanceof ko.bindingContext)
183.2062 -                    ? viewModelOrBindingContext
183.2063 -                    : new ko.bindingContext(ko.utils.unwrapObservable(viewModelOrBindingContext));
183.2064 -                var viewModel = bindingContextInstance['$data'];
183.2065 -
183.2066 -                // Optimization: Don't store the binding context on this node if it's definitely the same as on node.parentNode, because
183.2067 -                // we can easily recover it just by scanning up the node's ancestors in the DOM
183.2068 -                // (note: here, parent node means "real DOM parent" not "virtual parent", as there's no O(1) way to find the virtual parent)
183.2069 -                if (bindingContextMayDifferFromDomParentElement)
183.2070 -                    ko.storedBindingContextForNode(node, bindingContextInstance);
183.2071 -
183.2072 -                // Use evaluatedBindings if given, otherwise fall back on asking the bindings provider to give us some bindings
183.2073 -                var evaluatedBindings = (typeof bindings == "function") ? bindings(bindingContextInstance, node) : bindings;
183.2074 -                parsedBindings = evaluatedBindings || ko.bindingProvider['instance']['getBindings'](node, bindingContextInstance);
183.2075 -
183.2076 -                if (parsedBindings) {
183.2077 -                    // First run all the inits, so bindings can register for notification on changes
183.2078 -                    if (initPhase === 0) {
183.2079 -                        initPhase = 1;
183.2080 -                        for (var bindingKey in parsedBindings) {
183.2081 -                            var binding = ko.bindingHandlers[bindingKey];
183.2082 -                            if (binding && node.nodeType === 8)
183.2083 -                                validateThatBindingIsAllowedForVirtualElements(bindingKey);
183.2084 -
183.2085 -                            if (binding && typeof binding["init"] == "function") {
183.2086 -                                var handlerInitFn = binding["init"];
183.2087 -                                var initResult = handlerInitFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
183.2088 -
183.2089 -                                // If this binding handler claims to control descendant bindings, make a note of this
183.2090 -                                if (initResult && initResult['controlsDescendantBindings']) {
183.2091 -                                    if (bindingHandlerThatControlsDescendantBindings !== undefined)
183.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.");
183.2093 -                                    bindingHandlerThatControlsDescendantBindings = bindingKey;
183.2094 -                                }
183.2095 -                            }
183.2096 -                        }
183.2097 -                        initPhase = 2;
183.2098 -                    }
183.2099 -
183.2100 -                    // ... then run all the updates, which might trigger changes even on the first evaluation
183.2101 -                    if (initPhase === 2) {
183.2102 -                        for (var bindingKey in parsedBindings) {
183.2103 -                            var binding = ko.bindingHandlers[bindingKey];
183.2104 -                            if (binding && typeof binding["update"] == "function") {
183.2105 -                                var handlerUpdateFn = binding["update"];
183.2106 -                                handlerUpdateFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
183.2107 -                            }
183.2108 -                        }
183.2109 -                    }
183.2110 -                }
183.2111 -            },
183.2112 -            null,
183.2113 -            { disposeWhenNodeIsRemoved : node }
183.2114 -        );
183.2115 -
183.2116 -        return {
183.2117 -            shouldBindDescendants: bindingHandlerThatControlsDescendantBindings === undefined
183.2118 -        };
183.2119 -    };
183.2120 -
183.2121 -    var storedBindingContextDomDataKey = "__ko_bindingContext__";
183.2122 -    ko.storedBindingContextForNode = function (node, bindingContext) {
183.2123 -        if (arguments.length == 2)
183.2124 -            ko.utils.domData.set(node, storedBindingContextDomDataKey, bindingContext);
183.2125 -        else
183.2126 -            return ko.utils.domData.get(node, storedBindingContextDomDataKey);
183.2127 -    }
183.2128 -
183.2129 -    ko.applyBindingsToNode = function (node, bindings, viewModel) {
183.2130 -        if (node.nodeType === 1) // If it's an element, workaround IE <= 8 HTML parsing weirdness
183.2131 -            ko.virtualElements.normaliseVirtualElementDomStructure(node);
183.2132 -        return applyBindingsToNodeInternal(node, bindings, viewModel, true);
183.2133 -    };
183.2134 -
183.2135 -    ko.applyBindingsToDescendants = function(viewModel, rootNode) {
183.2136 -        if (rootNode.nodeType === 1 || rootNode.nodeType === 8)
183.2137 -            applyBindingsToDescendantsInternal(viewModel, rootNode, true);
183.2138 -    };
183.2139 -
183.2140 -    ko.applyBindings = function (viewModel, rootNode) {
183.2141 -        if (rootNode && (rootNode.nodeType !== 1) && (rootNode.nodeType !== 8))
183.2142 -            throw new Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");
183.2143 -        rootNode = rootNode || window.document.body; // Make "rootNode" parameter optional
183.2144 -
183.2145 -        applyBindingsToNodeAndDescendantsInternal(viewModel, rootNode, true);
183.2146 -    };
183.2147 -
183.2148 -    // Retrieving binding context from arbitrary nodes
183.2149 -    ko.contextFor = function(node) {
183.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)
183.2151 -        switch (node.nodeType) {
183.2152 -            case 1:
183.2153 -            case 8:
183.2154 -                var context = ko.storedBindingContextForNode(node);
183.2155 -                if (context) return context;
183.2156 -                if (node.parentNode) return ko.contextFor(node.parentNode);
183.2157 -                break;
183.2158 -        }
183.2159 -        return undefined;
183.2160 -    };
183.2161 -    ko.dataFor = function(node) {
183.2162 -        var context = ko.contextFor(node);
183.2163 -        return context ? context['$data'] : undefined;
183.2164 -    };
183.2165 -
183.2166 -    ko.exportSymbol('bindingHandlers', ko.bindingHandlers);
183.2167 -    ko.exportSymbol('applyBindings', ko.applyBindings);
183.2168 -    ko.exportSymbol('applyBindingsToDescendants', ko.applyBindingsToDescendants);
183.2169 -    ko.exportSymbol('applyBindingsToNode', ko.applyBindingsToNode);
183.2170 -    ko.exportSymbol('contextFor', ko.contextFor);
183.2171 -    ko.exportSymbol('dataFor', ko.dataFor);
183.2172 -})();
183.2173 -var attrHtmlToJavascriptMap = { 'class': 'className', 'for': 'htmlFor' };
183.2174 -ko.bindingHandlers['attr'] = {
183.2175 -    'update': function(element, valueAccessor, allBindingsAccessor) {
183.2176 -        var value = ko.utils.unwrapObservable(valueAccessor()) || {};
183.2177 -        for (var attrName in value) {
183.2178 -            if (typeof attrName == "string") {
183.2179 -                var attrValue = ko.utils.unwrapObservable(value[attrName]);
183.2180 -
183.2181 -                // To cover cases like "attr: { checked:someProp }", we want to remove the attribute entirely
183.2182 -                // when someProp is a "no value"-like value (strictly null, false, or undefined)
183.2183 -                // (because the absence of the "checked" attr is how to mark an element as not checked, etc.)
183.2184 -                var toRemove = (attrValue === false) || (attrValue === null) || (attrValue === undefined);
183.2185 -                if (toRemove)
183.2186 -                    element.removeAttribute(attrName);
183.2187 -
183.2188 -                // In IE <= 7 and IE8 Quirks Mode, you have to use the Javascript property name instead of the
183.2189 -                // HTML attribute name for certain attributes. IE8 Standards Mode supports the correct behavior,
183.2190 -                // but instead of figuring out the mode, we'll just set the attribute through the Javascript
183.2191 -                // property for IE <= 8.
183.2192 -                if (ko.utils.ieVersion <= 8 && attrName in attrHtmlToJavascriptMap) {
183.2193 -                    attrName = attrHtmlToJavascriptMap[attrName];
183.2194 -                    if (toRemove)
183.2195 -                        element.removeAttribute(attrName);
183.2196 -                    else
183.2197 -                        element[attrName] = attrValue;
183.2198 -                } else if (!toRemove) {
183.2199 -                    try {
183.2200 -                        element.setAttribute(attrName, attrValue.toString());
183.2201 -                    } catch (err) {
183.2202 -                        // ignore for now
183.2203 -                        if (console) {
183.2204 -                            console.log("Can't set attribute " + attrName + " to " + attrValue + " error: " + err);
183.2205 -                        }
183.2206 -                    }
183.2207 -                }
183.2208 -
183.2209 -                // Treat "name" specially - although you can think of it as an attribute, it also needs
183.2210 -                // special handling on older versions of IE (https://github.com/SteveSanderson/knockout/pull/333)
183.2211 -                // Deliberately being case-sensitive here because XHTML would regard "Name" as a different thing
183.2212 -                // entirely, and there's no strong reason to allow for such casing in HTML.
183.2213 -                if (attrName === "name") {
183.2214 -                    ko.utils.setElementName(element, toRemove ? "" : attrValue.toString());
183.2215 -                }
183.2216 -            }
183.2217 -        }
183.2218 -    }
183.2219 -};
183.2220 -ko.bindingHandlers['checked'] = {
183.2221 -    'init': function (element, valueAccessor, allBindingsAccessor) {
183.2222 -        var updateHandler = function() {
183.2223 -            var valueToWrite;
183.2224 -            if (element.type == "checkbox") {
183.2225 -                valueToWrite = element.checked;
183.2226 -            } else if ((element.type == "radio") && (element.checked)) {
183.2227 -                valueToWrite = element.value;
183.2228 -            } else {
183.2229 -                return; // "checked" binding only responds to checkboxes and selected radio buttons
183.2230 -            }
183.2231 -
183.2232 -            var modelValue = valueAccessor(), unwrappedValue = ko.utils.unwrapObservable(modelValue);
183.2233 -            if ((element.type == "checkbox") && (unwrappedValue instanceof Array)) {
183.2234 -                // For checkboxes bound to an array, we add/remove the checkbox value to that array
183.2235 -                // This works for both observable and non-observable arrays
183.2236 -                var existingEntryIndex = ko.utils.arrayIndexOf(unwrappedValue, element.value);
183.2237 -                if (element.checked && (existingEntryIndex < 0))
183.2238 -                    modelValue.push(element.value);
183.2239 -                else if ((!element.checked) && (existingEntryIndex >= 0))
183.2240 -                    modelValue.splice(existingEntryIndex, 1);
183.2241 -            } else {
183.2242 -                ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'checked', valueToWrite, true);
183.2243 -            }
183.2244 -        };
183.2245 -        ko.utils.registerEventHandler(element, "click", updateHandler);
183.2246 -
183.2247 -        // IE 6 won't allow radio buttons to be selected unless they have a name
183.2248 -        if ((element.type == "radio") && !element.name)
183.2249 -            ko.bindingHandlers['uniqueName']['init'](element, function() { return true });
183.2250 -    },
183.2251 -    'update': function (element, valueAccessor) {
183.2252 -        var value = ko.utils.unwrapObservable(valueAccessor());
183.2253 -
183.2254 -        if (element.type == "checkbox") {
183.2255 -            if (value instanceof Array) {
183.2256 -                // When bound to an array, the checkbox being checked represents its value being present in that array
183.2257 -                element.checked = ko.utils.arrayIndexOf(value, element.value) >= 0;
183.2258 -            } else {
183.2259 -                // When bound to anything other value (not an array), the checkbox being checked represents the value being trueish
183.2260 -                element.checked = value;
183.2261 -            }
183.2262 -        } else if (element.type == "radio") {
183.2263 -            element.checked = (element.value == value);
183.2264 -        }
183.2265 -    }
183.2266 -};
183.2267 -var classesWrittenByBindingKey = '__ko__cssValue';
183.2268 -ko.bindingHandlers['css'] = {
183.2269 -    'update': function (element, valueAccessor) {
183.2270 -        var value = ko.utils.unwrapObservable(valueAccessor());
183.2271 -        if (typeof value == "object") {
183.2272 -            for (var className in value) {
183.2273 -                var shouldHaveClass = ko.utils.unwrapObservable(value[className]);
183.2274 -                ko.utils.toggleDomNodeCssClass(element, className, shouldHaveClass);
183.2275 -            }
183.2276 -        } else {
183.2277 -            value = String(value || ''); // Make sure we don't try to store or set a non-string value
183.2278 -            ko.utils.toggleDomNodeCssClass(element, element[classesWrittenByBindingKey], false);
183.2279 -            element[classesWrittenByBindingKey] = value;
183.2280 -            ko.utils.toggleDomNodeCssClass(element, value, true);
183.2281 -        }
183.2282 -    }
183.2283 -};
183.2284 -ko.bindingHandlers['enable'] = {
183.2285 -    'update': function (element, valueAccessor) {
183.2286 -        var value = ko.utils.unwrapObservable(valueAccessor());
183.2287 -        if (value && element.disabled)
183.2288 -            element.removeAttribute("disabled");
183.2289 -        else if ((!value) && (!element.disabled))
183.2290 -            element.disabled = true;
183.2291 -    }
183.2292 -};
183.2293 -
183.2294 -ko.bindingHandlers['disable'] = {
183.2295 -    'update': function (element, valueAccessor) {
183.2296 -        ko.bindingHandlers['enable']['update'](element, function() { return !ko.utils.unwrapObservable(valueAccessor()) });
183.2297 -    }
183.2298 -};
183.2299 -// For certain common events (currently just 'click'), allow a simplified data-binding syntax
183.2300 -// e.g. click:handler instead of the usual full-length event:{click:handler}
183.2301 -function makeEventHandlerShortcut(eventName) {
183.2302 -    ko.bindingHandlers[eventName] = {
183.2303 -        'init': function(element, valueAccessor, allBindingsAccessor, viewModel) {
183.2304 -            var newValueAccessor = function () {
183.2305 -                var result = {};
183.2306 -                result[eventName] = valueAccessor();
183.2307 -                return result;
183.2308 -            };
183.2309 -            return ko.bindingHandlers['event']['init'].call(this, element, newValueAccessor, allBindingsAccessor, viewModel);
183.2310 -        }
183.2311 -    }
183.2312 -}
183.2313 -
183.2314 -ko.bindingHandlers['event'] = {
183.2315 -    'init' : function (element, valueAccessor, allBindingsAccessor, viewModel) {
183.2316 -        var eventsToHandle = valueAccessor() || {};
183.2317 -        for(var eventNameOutsideClosure in eventsToHandle) {
183.2318 -            (function() {
183.2319 -                var eventName = eventNameOutsideClosure; // Separate variable to be captured by event handler closure
183.2320 -                if (typeof eventName == "string") {
183.2321 -                    ko.utils.registerEventHandler(element, eventName, function (event) {
183.2322 -                        var handlerReturnValue;
183.2323 -                        var handlerFunction = valueAccessor()[eventName];
183.2324 -                        if (!handlerFunction)
183.2325 -                            return;
183.2326 -                        var allBindings = allBindingsAccessor();
183.2327 -
183.2328 -                        try {
183.2329 -                            // Take all the event args, and prefix with the viewmodel
183.2330 -                            var argsForHandler = ko.utils.makeArray(arguments);
183.2331 -                            argsForHandler.unshift(viewModel);
183.2332 -                            handlerReturnValue = handlerFunction.apply(viewModel, argsForHandler);
183.2333 -                        } finally {
183.2334 -                            if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
183.2335 -                                if (event.preventDefault)
183.2336 -                                    event.preventDefault();
183.2337 -                                else
183.2338 -                                    event.returnValue = false;
183.2339 -                            }
183.2340 -                        }
183.2341 -
183.2342 -                        var bubble = allBindings[eventName + 'Bubble'] !== false;
183.2343 -                        if (!bubble) {
183.2344 -                            event.cancelBubble = true;
183.2345 -                            if (event.stopPropagation)
183.2346 -                                event.stopPropagation();
183.2347 -                        }
183.2348 -                    });
183.2349 -                }
183.2350 -            })();
183.2351 -        }
183.2352 -    }
183.2353 -};
183.2354 -// "foreach: someExpression" is equivalent to "template: { foreach: someExpression }"
183.2355 -// "foreach: { data: someExpression, afterAdd: myfn }" is equivalent to "template: { foreach: someExpression, afterAdd: myfn }"
183.2356 -ko.bindingHandlers['foreach'] = {
183.2357 -    makeTemplateValueAccessor: function(valueAccessor) {
183.2358 -        return function() {
183.2359 -            var modelValue = valueAccessor(),
183.2360 -                unwrappedValue = ko.utils.peekObservable(modelValue);    // Unwrap without setting a dependency here
183.2361 -
183.2362 -            // If unwrappedValue is the array, pass in the wrapped value on its own
183.2363 -            // The value will be unwrapped and tracked within the template binding
183.2364 -            // (See https://github.com/SteveSanderson/knockout/issues/523)
183.2365 -            if ((!unwrappedValue) || typeof unwrappedValue.length == "number")
183.2366 -                return { 'foreach': modelValue, 'templateEngine': ko.nativeTemplateEngine.instance };
183.2367 -
183.2368 -            // If unwrappedValue.data is the array, preserve all relevant options and unwrap again value so we get updates
183.2369 -            ko.utils.unwrapObservable(modelValue);
183.2370 -            return {
183.2371 -                'foreach': unwrappedValue['data'],
183.2372 -                'as': unwrappedValue['as'],
183.2373 -                'includeDestroyed': unwrappedValue['includeDestroyed'],
183.2374 -                'afterAdd': unwrappedValue['afterAdd'],
183.2375 -                'beforeRemove': unwrappedValue['beforeRemove'],
183.2376 -                'afterRender': unwrappedValue['afterRender'],
183.2377 -                'beforeMove': unwrappedValue['beforeMove'],
183.2378 -                'afterMove': unwrappedValue['afterMove'],
183.2379 -                'templateEngine': ko.nativeTemplateEngine.instance
183.2380 -            };
183.2381 -        };
183.2382 -    },
183.2383 -    'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
183.2384 -        return ko.bindingHandlers['template']['init'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor));
183.2385 -    },
183.2386 -    'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
183.2387 -        return ko.bindingHandlers['template']['update'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor), allBindingsAccessor, viewModel, bindingContext);
183.2388 -    }
183.2389 -};
183.2390 -ko.expressionRewriting.bindingRewriteValidators['foreach'] = false; // Can't rewrite control flow bindings
183.2391 -ko.virtualElements.allowedBindings['foreach'] = true;
183.2392 -var hasfocusUpdatingProperty = '__ko_hasfocusUpdating';
183.2393 -ko.bindingHandlers['hasfocus'] = {
183.2394 -    'init': function(element, valueAccessor, allBindingsAccessor) {
183.2395 -        var handleElementFocusChange = function(isFocused) {
183.2396 -            // Where possible, ignore which event was raised and determine focus state using activeElement,
183.2397 -            // as this avoids phantom focus/blur events raised when changing tabs in modern browsers.
183.2398 -            // However, not all KO-targeted browsers (Firefox 2) support activeElement. For those browsers,
183.2399 -            // prevent a loss of focus when changing tabs/windows by setting a flag that prevents hasfocus
183.2400 -            // from calling 'blur()' on the element when it loses focus.
183.2401 -            // Discussion at https://github.com/SteveSanderson/knockout/pull/352
183.2402 -            element[hasfocusUpdatingProperty] = true;
183.2403 -            var ownerDoc = element.ownerDocument;
183.2404 -            if ("activeElement" in ownerDoc) {
183.2405 -                isFocused = (ownerDoc.activeElement === element);
183.2406 -            }
183.2407 -            var modelValue = valueAccessor();
183.2408 -            ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'hasfocus', isFocused, true);
183.2409 -            element[hasfocusUpdatingProperty] = false;
183.2410 -        };
183.2411 -        var handleElementFocusIn = handleElementFocusChange.bind(null, true);
183.2412 -        var handleElementFocusOut = handleElementFocusChange.bind(null, false);
183.2413 -
183.2414 -        ko.utils.registerEventHandler(element, "focus", handleElementFocusIn);
183.2415 -        ko.utils.registerEventHandler(element, "focusin", handleElementFocusIn); // For IE
183.2416 -        ko.utils.registerEventHandler(element, "blur",  handleElementFocusOut);
183.2417 -        ko.utils.registerEventHandler(element, "focusout",  handleElementFocusOut); // For IE
183.2418 -    },
183.2419 -    'update': function(element, valueAccessor) {
183.2420 -        var value = ko.utils.unwrapObservable(valueAccessor());
183.2421 -        if (!element[hasfocusUpdatingProperty]) {
183.2422 -            value ? element.focus() : element.blur();
183.2423 -            ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, value ? "focusin" : "focusout"]); // For IE, which doesn't reliably fire "focus" or "blur" events synchronously
183.2424 -        }
183.2425 -    }
183.2426 -};
183.2427 -ko.bindingHandlers['html'] = {
183.2428 -    'init': function() {
183.2429 -        // Prevent binding on the dynamically-injected HTML (as developers are unlikely to expect that, and it has security implications)
183.2430 -        return { 'controlsDescendantBindings': true };
183.2431 -    },
183.2432 -    'update': function (element, valueAccessor) {
183.2433 -        // setHtml will unwrap the value if needed
183.2434 -        ko.utils.setHtml(element, valueAccessor());
183.2435 -    }
183.2436 -};
183.2437 -var withIfDomDataKey = '__ko_withIfBindingData';
183.2438 -// Makes a binding like with or if
183.2439 -function makeWithIfBinding(bindingKey, isWith, isNot, makeContextCallback) {
183.2440 -    ko.bindingHandlers[bindingKey] = {
183.2441 -        'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
183.2442 -            ko.utils.domData.set(element, withIfDomDataKey, {});
183.2443 -            return { 'controlsDescendantBindings': true };
183.2444 -        },
183.2445 -        'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
183.2446 -            var withIfData = ko.utils.domData.get(element, withIfDomDataKey),
183.2447 -                dataValue = ko.utils.unwrapObservable(valueAccessor()),
183.2448 -                shouldDisplay = !isNot !== !dataValue, // equivalent to isNot ? !dataValue : !!dataValue
183.2449 -                isFirstRender = !withIfData.savedNodes,
183.2450 -                needsRefresh = isFirstRender || isWith || (shouldDisplay !== withIfData.didDisplayOnLastUpdate);
183.2451 -
183.2452 -            if (needsRefresh) {
183.2453 -                if (isFirstRender) {
183.2454 -                    withIfData.savedNodes = ko.utils.cloneNodes(ko.virtualElements.childNodes(element), true /* shouldCleanNodes */);
183.2455 -                }
183.2456 -
183.2457 -                if (shouldDisplay) {
183.2458 -                    if (!isFirstRender) {
183.2459 -                        ko.virtualElements.setDomNodeChildren(element, ko.utils.cloneNodes(withIfData.savedNodes));
183.2460 -                    }
183.2461 -                    ko.applyBindingsToDescendants(makeContextCallback ? makeContextCallback(bindingContext, dataValue) : bindingContext, element);
183.2462 -                } else {
183.2463 -                    ko.virtualElements.emptyNode(element);
183.2464 -                }
183.2465 -
183.2466 -                withIfData.didDisplayOnLastUpdate = shouldDisplay;
183.2467 -            }
183.2468 -        }
183.2469 -    };
183.2470 -    ko.expressionRewriting.bindingRewriteValidators[bindingKey] = false; // Can't rewrite control flow bindings
183.2471 -    ko.virtualElements.allowedBindings[bindingKey] = true;
183.2472 -}
183.2473 -
183.2474 -// Construct the actual binding handlers
183.2475 -makeWithIfBinding('if');
183.2476 -makeWithIfBinding('ifnot', false /* isWith */, true /* isNot */);
183.2477 -makeWithIfBinding('with', true /* isWith */, false /* isNot */,
183.2478 -    function(bindingContext, dataValue) {
183.2479 -        return bindingContext['createChildContext'](dataValue);
183.2480 -    }
183.2481 -);
183.2482 -function ensureDropdownSelectionIsConsistentWithModelValue(element, modelValue, preferModelValue) {
183.2483 -    if (preferModelValue) {
183.2484 -        if (modelValue !== ko.selectExtensions.readValue(element))
183.2485 -            ko.selectExtensions.writeValue(element, modelValue);
183.2486 -    }
183.2487 -
183.2488 -    // No matter which direction we're syncing in, we want the end result to be equality between dropdown value and model value.
183.2489 -    // If they aren't equal, either we prefer the dropdown value, or the model value couldn't be represented, so either way,
183.2490 -    // change the model value to match the dropdown.
183.2491 -    if (modelValue !== ko.selectExtensions.readValue(element))
183.2492 -        ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, "change"]);
183.2493 -};
183.2494 -
183.2495 -ko.bindingHandlers['options'] = {
183.2496 -    'update': function (element, valueAccessor, allBindingsAccessor) {
183.2497 -        if (ko.utils.tagNameLower(element) !== "select")
183.2498 -            throw new Error("options binding applies only to SELECT elements");
183.2499 -
183.2500 -        var selectWasPreviouslyEmpty = element.length == 0;
183.2501 -        var previousSelectedValues = ko.utils.arrayMap(ko.utils.arrayFilter(element.childNodes, function (node) {
183.2502 -            return node.tagName && (ko.utils.tagNameLower(node) === "option") && node.selected;
183.2503 -        }), function (node) {
183.2504 -            return ko.selectExtensions.readValue(node) || node.innerText || node.textContent;
183.2505 -        });
183.2506 -        var previousScrollTop = element.scrollTop;
183.2507 -
183.2508 -        var value = ko.utils.unwrapObservable(valueAccessor());
183.2509 -        var selectedValue = element.value;
183.2510 -
183.2511 -        // Remove all existing <option>s.
183.2512 -        // Need to use .remove() rather than .removeChild() for <option>s otherwise IE behaves oddly (https://github.com/SteveSanderson/knockout/issues/134)
183.2513 -        while (element.length > 0) {
183.2514 -            ko.cleanNode(element.options[0]);
183.2515 -            element.remove(0);
183.2516 -        }
183.2517 -
183.2518 -        if (value) {
183.2519 -            var allBindings = allBindingsAccessor(),
183.2520 -                includeDestroyed = allBindings['optionsIncludeDestroyed'];
183.2521 -
183.2522 -            if (typeof value.length != "number")
183.2523 -                value = [value];
183.2524 -            if (allBindings['optionsCaption']) {
183.2525 -                var option = document.createElement("option");
183.2526 -                ko.utils.setHtml(option, allBindings['optionsCaption']);
183.2527 -                ko.selectExtensions.writeValue(option, undefined);
183.2528 -                element.appendChild(option);
183.2529 -            }
183.2530 -
183.2531 -            for (var i = 0, j = value.length; i < j; i++) {
183.2532 -                // Skip destroyed items
183.2533 -                var arrayEntry = value[i];
183.2534 -                if (arrayEntry && arrayEntry['_destroy'] && !includeDestroyed)
183.2535 -                    continue;
183.2536 -
183.2537 -                var option = document.createElement("option");
183.2538 -
183.2539 -                function applyToObject(object, predicate, defaultValue) {
183.2540 -                    var predicateType = typeof predicate;
183.2541 -                    if (predicateType == "function")    // Given a function; run it against the data value
183.2542 -                        return predicate(object);
183.2543 -                    else if (predicateType == "string") // Given a string; treat it as a property name on the data value
183.2544 -                        return object[predicate];
183.2545 -                    else                                // Given no optionsText arg; use the data value itself
183.2546 -                        return defaultValue;
183.2547 -                }
183.2548 -
183.2549 -                // Apply a value to the option element
183.2550 -                var optionValue = applyToObject(arrayEntry, allBindings['optionsValue'], arrayEntry);
183.2551 -                ko.selectExtensions.writeValue(option, ko.utils.unwrapObservable(optionValue));
183.2552 -
183.2553 -                // Apply some text to the option element
183.2554 -                var optionText = applyToObject(arrayEntry, allBindings['optionsText'], optionValue);
183.2555 -                ko.utils.setTextContent(option, optionText);
183.2556 -
183.2557 -                element.appendChild(option);
183.2558 -            }
183.2559 -
183.2560 -            // IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document.
183.2561 -            // That's why we first added them without selection. Now it's time to set the selection.
183.2562 -            var newOptions = element.getElementsByTagName("option");
183.2563 -            var countSelectionsRetained = 0;
183.2564 -            for (var i = 0, j = newOptions.length; i < j; i++) {
183.2565 -                if (ko.utils.arrayIndexOf(previousSelectedValues, ko.selectExtensions.readValue(newOptions[i])) >= 0) {
183.2566 -                    ko.utils.setOptionNodeSelectionState(newOptions[i], true);
183.2567 -                    countSelectionsRetained++;
183.2568 -                }
183.2569 -            }
183.2570 -
183.2571 -            element.scrollTop = previousScrollTop;
183.2572 -
183.2573 -            if (selectWasPreviouslyEmpty && ('value' in allBindings)) {
183.2574 -                // Ensure consistency between model value and selected option.
183.2575 -                // If the dropdown is being populated for the first time here (or was otherwise previously empty),
183.2576 -                // the dropdown selection state is meaningless, so we preserve the model value.
183.2577 -                ensureDropdownSelectionIsConsistentWithModelValue(element, ko.utils.peekObservable(allBindings['value']), /* preferModelValue */ true);
183.2578 -            }
183.2579 -
183.2580 -            // Workaround for IE9 bug
183.2581 -            ko.utils.ensureSelectElementIsRenderedCorrectly(element);
183.2582 -        }
183.2583 -    }
183.2584 -};
183.2585 -ko.bindingHandlers['options'].optionValueDomDataKey = '__ko.optionValueDomData__';
183.2586 -ko.bindingHandlers['selectedOptions'] = {
183.2587 -    'init': function (element, valueAccessor, allBindingsAccessor) {
183.2588 -        ko.utils.registerEventHandler(element, "change", function () {
183.2589 -            var value = valueAccessor(), valueToWrite = [];
183.2590 -            ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
183.2591 -                if (node.selected)
183.2592 -                    valueToWrite.push(ko.selectExtensions.readValue(node));
183.2593 -            });
183.2594 -            ko.expressionRewriting.writeValueToProperty(value, allBindingsAccessor, 'value', valueToWrite);
183.2595 -        });
183.2596 -    },
183.2597 -    'update': function (element, valueAccessor) {
183.2598 -        if (ko.utils.tagNameLower(element) != "select")
183.2599 -            throw new Error("values binding applies only to SELECT elements");
183.2600 -
183.2601 -        var newValue = ko.utils.unwrapObservable(valueAccessor());
183.2602 -        if (newValue && typeof newValue.length == "number") {
183.2603 -            ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
183.2604 -                var isSelected = ko.utils.arrayIndexOf(newValue, ko.selectExtensions.readValue(node)) >= 0;
183.2605 -                ko.utils.setOptionNodeSelectionState(node, isSelected);
183.2606 -            });
183.2607 -        }
183.2608 -    }
183.2609 -};
183.2610 -ko.bindingHandlers['style'] = {
183.2611 -    'update': function (element, valueAccessor) {
183.2612 -        var value = ko.utils.unwrapObservable(valueAccessor() || {});
183.2613 -        for (var styleName in value) {
183.2614 -            if (typeof styleName == "string") {
183.2615 -                var styleValue = ko.utils.unwrapObservable(value[styleName]);
183.2616 -                element.style[styleName] = styleValue || ""; // Empty string removes the value, whereas null/undefined have no effect
183.2617 -            }
183.2618 -        }
183.2619 -    }
183.2620 -};
183.2621 -ko.bindingHandlers['submit'] = {
183.2622 -    'init': function (element, valueAccessor, allBindingsAccessor, viewModel) {
183.2623 -        if (typeof valueAccessor() != "function")
183.2624 -            throw new Error("The value for a submit binding must be a function");
183.2625 -        ko.utils.registerEventHandler(element, "submit", function (event) {
183.2626 -            var handlerReturnValue;
183.2627 -            var value = valueAccessor();
183.2628 -            try { handlerReturnValue = value.call(viewModel, element); }
183.2629 -            finally {
183.2630 -                if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
183.2631 -                    if (event.preventDefault)
183.2632 -                        event.preventDefault();
183.2633 -                    else
183.2634 -                        event.returnValue = false;
183.2635 -                }
183.2636 -            }
183.2637 -        });
183.2638 -    }
183.2639 -};
183.2640 -ko.bindingHandlers['text'] = {
183.2641 -    'update': function (element, valueAccessor) {
183.2642 -        ko.utils.setTextContent(element, valueAccessor());
183.2643 -    }
183.2644 -};
183.2645 -ko.virtualElements.allowedBindings['text'] = true;
183.2646 -ko.bindingHandlers['uniqueName'] = {
183.2647 -    'init': function (element, valueAccessor) {
183.2648 -        if (valueAccessor()) {
183.2649 -            var name = "ko_unique_" + (++ko.bindingHandlers['uniqueName'].currentIndex);
183.2650 -            ko.utils.setElementName(element, name);
183.2651 -        }
183.2652 -    }
183.2653 -};
183.2654 -ko.bindingHandlers['uniqueName'].currentIndex = 0;
183.2655 -ko.bindingHandlers['value'] = {
183.2656 -    'init': function (element, valueAccessor, allBindingsAccessor) {
183.2657 -        // Always catch "change" event; possibly other events too if asked
183.2658 -        var eventsToCatch = ["change"];
183.2659 -        var requestedEventsToCatch = allBindingsAccessor()["valueUpdate"];
183.2660 -        var propertyChangedFired = false;
183.2661 -        if (requestedEventsToCatch) {
183.2662 -            if (typeof requestedEventsToCatch == "string") // Allow both individual event names, and arrays of event names
183.2663 -                requestedEventsToCatch = [requestedEventsToCatch];
183.2664 -            ko.utils.arrayPushAll(eventsToCatch, requestedEventsToCatch);
183.2665 -            eventsToCatch = ko.utils.arrayGetDistinctValues(eventsToCatch);
183.2666 -        }
183.2667 -
183.2668 -        var valueUpdateHandler = function() {
183.2669 -            propertyChangedFired = false;
183.2670 -            var modelValue = valueAccessor();
183.2671 -            var elementValue = ko.selectExtensions.readValue(element);
183.2672 -            ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'value', elementValue);
183.2673 -        }
183.2674 -
183.2675 -        // Workaround for https://github.com/SteveSanderson/knockout/issues/122
183.2676 -        // IE doesn't fire "change" events on textboxes if the user selects a value from its autocomplete list
183.2677 -        var ieAutoCompleteHackNeeded = ko.utils.ieVersion && element.tagName.toLowerCase() == "input" && element.type == "text"
183.2678 -                                       && element.autocomplete != "off" && (!element.form || element.form.autocomplete != "off");
183.2679 -        if (ieAutoCompleteHackNeeded && ko.utils.arrayIndexOf(eventsToCatch, "propertychange") == -1) {
183.2680 -            ko.utils.registerEventHandler(element, "propertychange", function () { propertyChangedFired = true });
183.2681 -            ko.utils.registerEventHandler(element, "blur", function() {
183.2682 -                if (propertyChangedFired) {
183.2683 -                    valueUpdateHandler();
183.2684 -                }
183.2685 -            });
183.2686 -        }
183.2687 -
183.2688 -        ko.utils.arrayForEach(eventsToCatch, function(eventName) {
183.2689 -            // The syntax "after<eventname>" means "run the handler asynchronously after the event"
183.2690 -            // This is useful, for example, to catch "keydown" events after the browser has updated the control
183.2691 -            // (otherwise, ko.selectExtensions.readValue(this) will receive the control's value *before* the key event)
183.2692 -            var handler = valueUpdateHandler;
183.2693 -            if (ko.utils.stringStartsWith(eventName, "after")) {
183.2694 -                handler = function() { setTimeout(valueUpdateHandler, 0) };
183.2695 -                eventName = eventName.substring("after".length);
183.2696 -            }
183.2697 -            ko.utils.registerEventHandler(element, eventName, handler);
183.2698 -        });
183.2699 -    },
183.2700 -    'update': function (element, valueAccessor) {
183.2701 -        var valueIsSelectOption = ko.utils.tagNameLower(element) === "select";
183.2702 -        var newValue = ko.utils.unwrapObservable(valueAccessor());
183.2703 -        var elementValue = ko.selectExtensions.readValue(element);
183.2704 -        var valueHasChanged = (newValue != elementValue);
183.2705 -
183.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).
183.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.
183.2708 -        if ((newValue === 0) && (elementValue !== 0) && (elementValue !== "0"))
183.2709 -            valueHasChanged = true;
183.2710 -
183.2711 -        if (valueHasChanged) {
183.2712 -            var applyValueAction = function () { ko.selectExtensions.writeValue(element, newValue); };
183.2713 -            applyValueAction();
183.2714 -
183.2715 -            // Workaround for IE6 bug: It won't reliably apply values to SELECT nodes during the same execution thread
183.2716 -            // right after you've changed the set of OPTION nodes on it. So for that node type, we'll schedule a second thread
183.2717 -            // to apply the value as well.
183.2718 -            var alsoApplyAsynchronously = valueIsSelectOption;
183.2719 -            if (alsoApplyAsynchronously)
183.2720 -                setTimeout(applyValueAction, 0);
183.2721 -        }
183.2722 -
183.2723 -        // If you try to set a model value that can't be represented in an already-populated dropdown, reject that change,
183.2724 -        // because you're not allowed to have a model value that disagrees with a visible UI selection.
183.2725 -        if (valueIsSelectOption && (element.length > 0))
183.2726 -            ensureDropdownSelectionIsConsistentWithModelValue(element, newValue, /* preferModelValue */ false);
183.2727 -    }
183.2728 -};
183.2729 -ko.bindingHandlers['visible'] = {
183.2730 -    'update': function (element, valueAccessor) {
183.2731 -        var value = ko.utils.unwrapObservable(valueAccessor());
183.2732 -        var isCurrentlyVisible = !(element.style.display == "none");
183.2733 -        if (value && !isCurrentlyVisible)
183.2734 -            element.style.display = "";
183.2735 -        else if ((!value) && isCurrentlyVisible)
183.2736 -            element.style.display = "none";
183.2737 -    }
183.2738 -};
183.2739 -// 'click' is just a shorthand for the usual full-length event:{click:handler}
183.2740 -makeEventHandlerShortcut('click');
183.2741 -// If you want to make a custom template engine,
183.2742 -//
183.2743 -// [1] Inherit from this class (like ko.nativeTemplateEngine does)
183.2744 -// [2] Override 'renderTemplateSource', supplying a function with this signature:
183.2745 -//
183.2746 -//        function (templateSource, bindingContext, options) {
183.2747 -//            // - templateSource.text() is the text of the template you should render
183.2748 -//            // - bindingContext.$data is the data you should pass into the template
183.2749 -//            //   - you might also want to make bindingContext.$parent, bindingContext.$parents,
183.2750 -//            //     and bindingContext.$root available in the template too
183.2751 -//            // - options gives you access to any other properties set on "data-bind: { template: options }"
183.2752 -//            //
183.2753 -//            // Return value: an array of DOM nodes
183.2754 -//        }
183.2755 -//
183.2756 -// [3] Override 'createJavaScriptEvaluatorBlock', supplying a function with this signature:
183.2757 -//
183.2758 -//        function (script) {
183.2759 -//            // Return value: Whatever syntax means "Evaluate the JavaScript statement 'script' and output the result"
183.2760 -//            //               For example, the jquery.tmpl template engine converts 'someScript' to '${ someScript }'
183.2761 -//        }
183.2762 -//
183.2763 -//     This is only necessary if you want to allow data-bind attributes to reference arbitrary template variables.
183.2764 -//     If you don't want to allow that, you can set the property 'allowTemplateRewriting' to false (like ko.nativeTemplateEngine does)
183.2765 -//     and then you don't need to override 'createJavaScriptEvaluatorBlock'.
183.2766 -
183.2767 -ko.templateEngine = function () { };
183.2768 -
183.2769 -ko.templateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
183.2770 -    throw new Error("Override renderTemplateSource");
183.2771 -};
183.2772 -
183.2773 -ko.templateEngine.prototype['createJavaScriptEvaluatorBlock'] = function (script) {
183.2774 -    throw new Error("Override createJavaScriptEvaluatorBlock");
183.2775 -};
183.2776 -
183.2777 -ko.templateEngine.prototype['makeTemplateSource'] = function(template, templateDocument) {
183.2778 -    // Named template
183.2779 -    if (typeof template == "string") {
183.2780 -        templateDocument = templateDocument || document;
183.2781 -        var elem = templateDocument.getElementById(template);
183.2782 -        if (!elem)
183.2783 -            throw new Error("Cannot find template with ID " + template);
183.2784 -        return new ko.templateSources.domElement(elem);
183.2785 -    } else if ((template.nodeType == 1) || (template.nodeType == 8)) {
183.2786 -        // Anonymous template
183.2787 -        return new ko.templateSources.anonymousTemplate(template);
183.2788 -    } else
183.2789 -        throw new Error("Unknown template type: " + template);
183.2790 -};
183.2791 -
183.2792 -ko.templateEngine.prototype['renderTemplate'] = function (template, bindingContext, options, templateDocument) {
183.2793 -    var templateSource = this['makeTemplateSource'](template, templateDocument);
183.2794 -    return this['renderTemplateSource'](templateSource, bindingContext, options);
183.2795 -};
183.2796 -
183.2797 -ko.templateEngine.prototype['isTemplateRewritten'] = function (template, templateDocument) {
183.2798 -    // Skip rewriting if requested
183.2799 -    if (this['allowTemplateRewriting'] === false)
183.2800 -        return true;
183.2801 -    return this['makeTemplateSource'](template, templateDocument)['data']("isRewritten");
183.2802 -};
183.2803 -
183.2804 -ko.templateEngine.prototype['rewriteTemplate'] = function (template, rewriterCallback, templateDocument) {
183.2805 -    var templateSource = this['makeTemplateSource'](template, templateDocument);
183.2806 -    var rewritten = rewriterCallback(templateSource['text']());
183.2807 -    templateSource['text'](rewritten);
183.2808 -    templateSource['data']("isRewritten", true);
183.2809 -};
183.2810 -
183.2811 -ko.exportSymbol('templateEngine', ko.templateEngine);
183.2812 -
183.2813 -ko.templateRewriting = (function () {
183.2814 -    var memoizeDataBindingAttributeSyntaxRegex = /(<[a-z]+\d*(\s+(?!data-bind=)[a-z0-9\-]+(=(\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind=(["'])([\s\S]*?)\5/gi;
183.2815 -    var memoizeVirtualContainerBindingSyntaxRegex = /<!--\s*ko\b\s*([\s\S]*?)\s*-->/g;
183.2816 -
183.2817 -    function validateDataBindValuesForRewriting(keyValueArray) {
183.2818 -        var allValidators = ko.expressionRewriting.bindingRewriteValidators;
183.2819 -        for (var i = 0; i < keyValueArray.length; i++) {
183.2820 -            var key = keyValueArray[i]['key'];
183.2821 -            if (allValidators.hasOwnProperty(key)) {
183.2822 -                var validator = allValidators[key];
183.2823 -
183.2824 -                if (typeof validator === "function") {
183.2825 -                    var possibleErrorMessage = validator(keyValueArray[i]['value']);
183.2826 -                    if (possibleErrorMessage)
183.2827 -                        throw new Error(possibleErrorMessage);
183.2828 -                } else if (!validator) {
183.2829 -                    throw new Error("This template engine does not support the '" + key + "' binding within its templates");
183.2830 -                }
183.2831 -            }
183.2832 -        }
183.2833 -    }
183.2834 -
183.2835 -    function constructMemoizedTagReplacement(dataBindAttributeValue, tagToRetain, templateEngine) {
183.2836 -        var dataBindKeyValueArray = ko.expressionRewriting.parseObjectLiteral(dataBindAttributeValue);
183.2837 -        validateDataBindValuesForRewriting(dataBindKeyValueArray);
183.2838 -        var rewrittenDataBindAttributeValue = ko.expressionRewriting.preProcessBindings(dataBindKeyValueArray);
183.2839 -
183.2840 -        // For no obvious reason, Opera fails to evaluate rewrittenDataBindAttributeValue unless it's wrapped in an additional
183.2841 -        // anonymous function, even though Opera's built-in debugger can evaluate it anyway. No other browser requires this
183.2842 -        // extra indirection.
183.2843 -        var applyBindingsToNextSiblingScript =
183.2844 -            "ko.__tr_ambtns(function($context,$element){return(function(){return{ " + rewrittenDataBindAttributeValue + " } })()})";
183.2845 -        return templateEngine['createJavaScriptEvaluatorBlock'](applyBindingsToNextSiblingScript) + tagToRetain;
183.2846 -    }
183.2847 -
183.2848 -    return {
183.2849 -        ensureTemplateIsRewritten: function (template, templateEngine, templateDocument) {
183.2850 -            if (!templateEngine['isTemplateRewritten'](template, templateDocument))
183.2851 -                templateEngine['rewriteTemplate'](template, function (htmlString) {
183.2852 -                    return ko.templateRewriting.memoizeBindingAttributeSyntax(htmlString, templateEngine);
183.2853 -                }, templateDocument);
183.2854 -        },
183.2855 -
183.2856 -        memoizeBindingAttributeSyntax: function (htmlString, templateEngine) {
183.2857 -            return htmlString.replace(memoizeDataBindingAttributeSyntaxRegex, function () {
183.2858 -                return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[6], /* tagToRetain: */ arguments[1], templateEngine);
183.2859 -            }).replace(memoizeVirtualContainerBindingSyntaxRegex, function() {
183.2860 -                return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[1], /* tagToRetain: */ "<!-- ko -->", templateEngine);
183.2861 -            });
183.2862 -        },
183.2863 -
183.2864 -        applyMemoizedBindingsToNextSibling: function (bindings) {
183.2865 -            return ko.memoization.memoize(function (domNode, bindingContext) {
183.2866 -                if (domNode.nextSibling)
183.2867 -                    ko.applyBindingsToNode(domNode.nextSibling, bindings, bindingContext);
183.2868 -            });
183.2869 -        }
183.2870 -    }
183.2871 -})();
183.2872 -
183.2873 -
183.2874 -// Exported only because it has to be referenced by string lookup from within rewritten template
183.2875 -ko.exportSymbol('__tr_ambtns', ko.templateRewriting.applyMemoizedBindingsToNextSibling);
183.2876 -(function() {
183.2877 -    // A template source represents a read/write way of accessing a template. This is to eliminate the need for template loading/saving
183.2878 -    // logic to be duplicated in every template engine (and means they can all work with anonymous templates, etc.)
183.2879 -    //
183.2880 -    // Two are provided by default:
183.2881 -    //  1. ko.templateSources.domElement       - reads/writes the text content of an arbitrary DOM element
183.2882 -    //  2. ko.templateSources.anonymousElement - uses ko.utils.domData to read/write text *associated* with the DOM element, but
183.2883 -    //                                           without reading/writing the actual element text content, since it will be overwritten
183.2884 -    //                                           with the rendered template output.
183.2885 -    // You can implement your own template source if you want to fetch/store templates somewhere other than in DOM elements.
183.2886 -    // Template sources need to have the following functions:
183.2887 -    //   text() 			- returns the template text from your storage location
183.2888 -    //   text(value)		- writes the supplied template text to your storage location
183.2889 -    //   data(key)			- reads values stored using data(key, value) - see below
183.2890 -    //   data(key, value)	- associates "value" with this template and the key "key". Is used to store information like "isRewritten".
183.2891 -    //
183.2892 -    // Optionally, template sources can also have the following functions:
183.2893 -    //   nodes()            - returns a DOM element containing the nodes of this template, where available
183.2894 -    //   nodes(value)       - writes the given DOM element to your storage location
183.2895 -    // If a DOM element is available for a given template source, template engines are encouraged to use it in preference over text()
183.2896 -    // for improved speed. However, all templateSources must supply text() even if they don't supply nodes().
183.2897 -    //
183.2898 -    // Once you've implemented a templateSource, make your template engine use it by subclassing whatever template engine you were
183.2899 -    // using and overriding "makeTemplateSource" to return an instance of your custom template source.
183.2900 -
183.2901 -    ko.templateSources = {};
183.2902 -
183.2903 -    // ---- ko.templateSources.domElement -----
183.2904 -
183.2905 -    ko.templateSources.domElement = function(element) {
183.2906 -        this.domElement = element;
183.2907 -    }
183.2908 -
183.2909 -    ko.templateSources.domElement.prototype['text'] = function(/* valueToWrite */) {
183.2910 -        var tagNameLower = ko.utils.tagNameLower(this.domElement),
183.2911 -            elemContentsProperty = tagNameLower === "script" ? "text"
183.2912 -                                 : tagNameLower === "textarea" ? "value"
183.2913 -                                 : "innerHTML";
183.2914 -
183.2915 -        if (arguments.length == 0) {
183.2916 -            return this.domElement[elemContentsProperty];
183.2917 -        } else {
183.2918 -            var valueToWrite = arguments[0];
183.2919 -            if (elemContentsProperty === "innerHTML")
183.2920 -                ko.utils.setHtml(this.domElement, valueToWrite);
183.2921 -            else
183.2922 -                this.domElement[elemContentsProperty] = valueToWrite;
183.2923 -        }
183.2924 -    };
183.2925 -
183.2926 -    ko.templateSources.domElement.prototype['data'] = function(key /*, valueToWrite */) {
183.2927 -        if (arguments.length === 1) {
183.2928 -            return ko.utils.domData.get(this.domElement, "templateSourceData_" + key);
183.2929 -        } else {
183.2930 -            ko.utils.domData.set(this.domElement, "templateSourceData_" + key, arguments[1]);
183.2931 -        }
183.2932 -    };
183.2933 -
183.2934 -    // ---- ko.templateSources.anonymousTemplate -----
183.2935 -    // Anonymous templates are normally saved/retrieved as DOM nodes through "nodes".
183.2936 -    // For compatibility, you can also read "text"; it will be serialized from the nodes on demand.
183.2937 -    // Writing to "text" is still supported, but then the template data will not be available as DOM nodes.
183.2938 -
183.2939 -    var anonymousTemplatesDomDataKey = "__ko_anon_template__";
183.2940 -    ko.templateSources.anonymousTemplate = function(element) {
183.2941 -        this.domElement = element;
183.2942 -    }
183.2943 -    ko.templateSources.anonymousTemplate.prototype = new ko.templateSources.domElement();
183.2944 -    ko.templateSources.anonymousTemplate.prototype['text'] = function(/* valueToWrite */) {
183.2945 -        if (arguments.length == 0) {
183.2946 -            var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
183.2947 -            if (templateData.textData === undefined && templateData.containerData)
183.2948 -                templateData.textData = templateData.containerData.innerHTML;
183.2949 -            return templateData.textData;
183.2950 -        } else {
183.2951 -            var valueToWrite = arguments[0];
183.2952 -            ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {textData: valueToWrite});
183.2953 -        }
183.2954 -    };
183.2955 -    ko.templateSources.domElement.prototype['nodes'] = function(/* valueToWrite */) {
183.2956 -        if (arguments.length == 0) {
183.2957 -            var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
183.2958 -            return templateData.containerData;
183.2959 -        } else {
183.2960 -            var valueToWrite = arguments[0];
183.2961 -            ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {containerData: valueToWrite});
183.2962 -        }
183.2963 -    };
183.2964 -
183.2965 -    ko.exportSymbol('templateSources', ko.templateSources);
183.2966 -    ko.exportSymbol('templateSources.domElement', ko.templateSources.domElement);
183.2967 -    ko.exportSymbol('templateSources.anonymousTemplate', ko.templateSources.anonymousTemplate);
183.2968 -})();
183.2969 -(function () {
183.2970 -    var _templateEngine;
183.2971 -    ko.setTemplateEngine = function (templateEngine) {
183.2972 -        if ((templateEngine != undefined) && !(templateEngine instanceof ko.templateEngine))
183.2973 -            throw new Error("templateEngine must inherit from ko.templateEngine");
183.2974 -        _templateEngine = templateEngine;
183.2975 -    }
183.2976 -
183.2977 -    function invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, action) {
183.2978 -        var node, nextInQueue = firstNode, firstOutOfRangeNode = ko.virtualElements.nextSibling(lastNode);
183.2979 -        while (nextInQueue && ((node = nextInQueue) !== firstOutOfRangeNode)) {
183.2980 -            nextInQueue = ko.virtualElements.nextSibling(node);
183.2981 -            if (node.nodeType === 1 || node.nodeType === 8)
183.2982 -                action(node);
183.2983 -        }
183.2984 -    }
183.2985 -
183.2986 -    function activateBindingsOnContinuousNodeArray(continuousNodeArray, bindingContext) {
183.2987 -        // To be used on any nodes that have been rendered by a template and have been inserted into some parent element
183.2988 -        // Walks through continuousNodeArray (which *must* be continuous, i.e., an uninterrupted sequence of sibling nodes, because
183.2989 -        // the algorithm for walking them relies on this), and for each top-level item in the virtual-element sense,
183.2990 -        // (1) Does a regular "applyBindings" to associate bindingContext with this node and to activate any non-memoized bindings
183.2991 -        // (2) Unmemoizes any memos in the DOM subtree (e.g., to activate bindings that had been memoized during template rewriting)
183.2992 -
183.2993 -        if (continuousNodeArray.length) {
183.2994 -            var firstNode = continuousNodeArray[0], lastNode = continuousNodeArray[continuousNodeArray.length - 1];
183.2995 -
183.2996 -            // Need to applyBindings *before* unmemoziation, because unmemoization might introduce extra nodes (that we don't want to re-bind)
183.2997 -            // whereas a regular applyBindings won't introduce new memoized nodes
183.2998 -            invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
183.2999 -                ko.applyBindings(bindingContext, node);
183.3000 -            });
183.3001 -            invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
183.3002 -                ko.memoization.unmemoizeDomNodeAndDescendants(node, [bindingContext]);
183.3003 -            });
183.3004 -        }
183.3005 -    }
183.3006 -
183.3007 -    function getFirstNodeFromPossibleArray(nodeOrNodeArray) {
183.3008 -        return nodeOrNodeArray.nodeType ? nodeOrNodeArray
183.3009 -                                        : nodeOrNodeArray.length > 0 ? nodeOrNodeArray[0]
183.3010 -                                        : null;
183.3011 -    }
183.3012 -
183.3013 -    function executeTemplate(targetNodeOrNodeArray, renderMode, template, bindingContext, options) {
183.3014 -        options = options || {};
183.3015 -        var firstTargetNode = targetNodeOrNodeArray && getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
183.3016 -        var templateDocument = firstTargetNode && firstTargetNode.ownerDocument;
183.3017 -        var templateEngineToUse = (options['templateEngine'] || _templateEngine);
183.3018 -        ko.templateRewriting.ensureTemplateIsRewritten(template, templateEngineToUse, templateDocument);
183.3019 -        var renderedNodesArray = templateEngineToUse['renderTemplate'](template, bindingContext, options, templateDocument);
183.3020 -
183.3021 -        // Loosely check result is an array of DOM nodes
183.3022 -        if ((typeof renderedNodesArray.length != "number") || (renderedNodesArray.length > 0 && typeof renderedNodesArray[0].nodeType != "number"))
183.3023 -            throw new Error("Template engine must return an array of DOM nodes");
183.3024 -
183.3025 -        var haveAddedNodesToParent = false;
183.3026 -        switch (renderMode) {
183.3027 -            case "replaceChildren":
183.3028 -                ko.virtualElements.setDomNodeChildren(targetNodeOrNodeArray, renderedNodesArray);
183.3029 -                haveAddedNodesToParent = true;
183.3030 -                break;
183.3031 -            case "replaceNode":
183.3032 -                ko.utils.replaceDomNodes(targetNodeOrNodeArray, renderedNodesArray);
183.3033 -                haveAddedNodesToParent = true;
183.3034 -                break;
183.3035 -            case "ignoreTargetNode": break;
183.3036 -            default:
183.3037 -                throw new Error("Unknown renderMode: " + renderMode);
183.3038 -        }
183.3039 -
183.3040 -        if (haveAddedNodesToParent) {
183.3041 -            activateBindingsOnContinuousNodeArray(renderedNodesArray, bindingContext);
183.3042 -            if (options['afterRender'])
183.3043 -                ko.dependencyDetection.ignore(options['afterRender'], null, [renderedNodesArray, bindingContext['$data']]);
183.3044 -        }
183.3045 -
183.3046 -        return renderedNodesArray;
183.3047 -    }
183.3048 -
183.3049 -    ko.renderTemplate = function (template, dataOrBindingContext, options, targetNodeOrNodeArray, renderMode) {
183.3050 -        options = options || {};
183.3051 -        if ((options['templateEngine'] || _templateEngine) == undefined)
183.3052 -            throw new Error("Set a template engine before calling renderTemplate");
183.3053 -        renderMode = renderMode || "replaceChildren";
183.3054 -
183.3055 -        if (targetNodeOrNodeArray) {
183.3056 -            var firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
183.3057 -
183.3058 -            var whenToDispose = function () { return (!firstTargetNode) || !ko.utils.domNodeIsAttachedToDocument(firstTargetNode); }; // Passive disposal (on next evaluation)
183.3059 -            var activelyDisposeWhenNodeIsRemoved = (firstTargetNode && renderMode == "replaceNode") ? firstTargetNode.parentNode : firstTargetNode;
183.3060 -
183.3061 -            return ko.dependentObservable( // So the DOM is automatically updated when any dependency changes
183.3062 -                function () {
183.3063 -                    // Ensure we've got a proper binding context to work with
183.3064 -                    var bindingContext = (dataOrBindingContext && (dataOrBindingContext instanceof ko.bindingContext))
183.3065 -                        ? dataOrBindingContext
183.3066 -                        : new ko.bindingContext(ko.utils.unwrapObservable(dataOrBindingContext));
183.3067 -
183.3068 -                    // Support selecting template as a function of the data being rendered
183.3069 -                    var templateName = typeof(template) == 'function' ? template(bindingContext['$data'], bindingContext) : template;
183.3070 -
183.3071 -                    var renderedNodesArray = executeTemplate(targetNodeOrNodeArray, renderMode, templateName, bindingContext, options);
183.3072 -                    if (renderMode == "replaceNode") {
183.3073 -                        targetNodeOrNodeArray = renderedNodesArray;
183.3074 -                        firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
183.3075 -                    }
183.3076 -                },
183.3077 -                null,
183.3078 -                { disposeWhen: whenToDispose, disposeWhenNodeIsRemoved: activelyDisposeWhenNodeIsRemoved }
183.3079 -            );
183.3080 -        } else {
183.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
183.3082 -            return ko.memoization.memoize(function (domNode) {
183.3083 -                ko.renderTemplate(template, dataOrBindingContext, options, domNode, "replaceNode");
183.3084 -            });
183.3085 -        }
183.3086 -    };
183.3087 -
183.3088 -    ko.renderTemplateForEach = function (template, arrayOrObservableArray, options, targetNode, parentBindingContext) {
183.3089 -        // Since setDomNodeChildrenFromArrayMapping always calls executeTemplateForArrayItem and then
183.3090 -        // activateBindingsCallback for added items, we can store the binding context in the former to use in the latter.
183.3091 -        var arrayItemContext;
183.3092 -
183.3093 -        // This will be called by setDomNodeChildrenFromArrayMapping to get the nodes to add to targetNode
183.3094 -        var executeTemplateForArrayItem = function (arrayValue, index) {
183.3095 -            // Support selecting template as a function of the data being rendered
183.3096 -            arrayItemContext = parentBindingContext['createChildContext'](ko.utils.unwrapObservable(arrayValue), options['as']);
183.3097 -            arrayItemContext['$index'] = index;
183.3098 -            var templateName = typeof(template) == 'function' ? template(arrayValue, arrayItemContext) : template;
183.3099 -            return executeTemplate(null, "ignoreTargetNode", templateName, arrayItemContext, options);
183.3100 -        }
183.3101 -
183.3102 -        // This will be called whenever setDomNodeChildrenFromArrayMapping has added nodes to targetNode
183.3103 -        var activateBindingsCallback = function(arrayValue, addedNodesArray, index) {
183.3104 -            activateBindingsOnContinuousNodeArray(addedNodesArray, arrayItemContext);
183.3105 -            if (options['afterRender'])
183.3106 -                options['afterRender'](addedNodesArray, arrayValue);
183.3107 -        };
183.3108 -
183.3109 -        return ko.dependentObservable(function () {
183.3110 -            var unwrappedArray = ko.utils.unwrapObservable(arrayOrObservableArray) || [];
183.3111 -            if (typeof unwrappedArray.length == "undefined") // Coerce single value into array
183.3112 -                unwrappedArray = [unwrappedArray];
183.3113 -
183.3114 -            // Filter out any entries marked as destroyed
183.3115 -            var filteredArray = ko.utils.arrayFilter(unwrappedArray, function(item) {
183.3116 -                return options['includeDestroyed'] || item === undefined || item === null || !ko.utils.unwrapObservable(item['_destroy']);
183.3117 -            });
183.3118 -
183.3119 -            // Call setDomNodeChildrenFromArrayMapping, ignoring any observables unwrapped within (most likely from a callback function).
183.3120 -            // If the array items are observables, though, they will be unwrapped in executeTemplateForArrayItem and managed within setDomNodeChildrenFromArrayMapping.
183.3121 -            ko.dependencyDetection.ignore(ko.utils.setDomNodeChildrenFromArrayMapping, null, [targetNode, filteredArray, executeTemplateForArrayItem, options, activateBindingsCallback]);
183.3122 -
183.3123 -        }, null, { disposeWhenNodeIsRemoved: targetNode });
183.3124 -    };
183.3125 -
183.3126 -    var templateComputedDomDataKey = '__ko__templateComputedDomDataKey__';
183.3127 -    function disposeOldComputedAndStoreNewOne(element, newComputed) {
183.3128 -        var oldComputed = ko.utils.domData.get(element, templateComputedDomDataKey);
183.3129 -        if (oldComputed && (typeof(oldComputed.dispose) == 'function'))
183.3130 -            oldComputed.dispose();
183.3131 -        ko.utils.domData.set(element, templateComputedDomDataKey, (newComputed && newComputed.isActive()) ? newComputed : undefined);
183.3132 -    }
183.3133 -
183.3134 -    ko.bindingHandlers['template'] = {
183.3135 -        'init': function(element, valueAccessor) {
183.3136 -            // Support anonymous templates
183.3137 -            var bindingValue = ko.utils.unwrapObservable(valueAccessor());
183.3138 -            if ((typeof bindingValue != "string") && (!bindingValue['name']) && (element.nodeType == 1 || element.nodeType == 8)) {
183.3139 -                // It's an anonymous template - store the element contents, then clear the element
183.3140 -                var templateNodes = element.nodeType == 1 ? element.childNodes : ko.virtualElements.childNodes(element),
183.3141 -                    container = ko.utils.moveCleanedNodesToContainerElement(templateNodes); // This also removes the nodes from their current parent
183.3142 -                new ko.templateSources.anonymousTemplate(element)['nodes'](container);
183.3143 -            }
183.3144 -            return { 'controlsDescendantBindings': true };
183.3145 -        },
183.3146 -        'update': function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
183.3147 -            var templateName = ko.utils.unwrapObservable(valueAccessor()),
183.3148 -                options = {},
183.3149 -                shouldDisplay = true,
183.3150 -                dataValue,
183.3151 -                templateComputed = null;
183.3152 -
183.3153 -            if (typeof templateName != "string") {
183.3154 -                options = templateName;
183.3155 -                templateName = options['name'];
183.3156 -
183.3157 -                // Support "if"/"ifnot" conditions
183.3158 -                if ('if' in options)
183.3159 -                    shouldDisplay = ko.utils.unwrapObservable(options['if']);
183.3160 -                if (shouldDisplay && 'ifnot' in options)
183.3161 -                    shouldDisplay = !ko.utils.unwrapObservable(options['ifnot']);
183.3162 -
183.3163 -                dataValue = ko.utils.unwrapObservable(options['data']);
183.3164 -            }
183.3165 -
183.3166 -            if ('foreach' in options) {
183.3167 -                // Render once for each data point (treating data set as empty if shouldDisplay==false)
183.3168 -                var dataArray = (shouldDisplay && options['foreach']) || [];
183.3169 -                templateComputed = ko.renderTemplateForEach(templateName || element, dataArray, options, element, bindingContext);
183.3170 -            } else if (!shouldDisplay) {
183.3171 -                ko.virtualElements.emptyNode(element);
183.3172 -            } else {
183.3173 -                // Render once for this single data point (or use the viewModel if no data was provided)
183.3174 -                var innerBindingContext = ('data' in options) ?
183.3175 -                    bindingContext['createChildContext'](dataValue, options['as']) :  // Given an explitit 'data' value, we create a child binding context for it
183.3176 -                    bindingContext;                                                        // Given no explicit 'data' value, we retain the same binding context
183.3177 -                templateComputed = ko.renderTemplate(templateName || element, innerBindingContext, options, element);
183.3178 -            }
183.3179 -
183.3180 -            // It only makes sense to have a single template computed per element (otherwise which one should have its output displayed?)
183.3181 -            disposeOldComputedAndStoreNewOne(element, templateComputed);
183.3182 -        }
183.3183 -    };
183.3184 -
183.3185 -    // Anonymous templates can't be rewritten. Give a nice error message if you try to do it.
183.3186 -    ko.expressionRewriting.bindingRewriteValidators['template'] = function(bindingValue) {
183.3187 -        var parsedBindingValue = ko.expressionRewriting.parseObjectLiteral(bindingValue);
183.3188 -
183.3189 -        if ((parsedBindingValue.length == 1) && parsedBindingValue[0]['unknown'])
183.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)
183.3191 -
183.3192 -        if (ko.expressionRewriting.keyValueArrayContainsKey(parsedBindingValue, "name"))
183.3193 -            return null; // Named templates can be rewritten, so return "no error"
183.3194 -        return "This template engine does not support anonymous templates nested within its templates";
183.3195 -    };
183.3196 -
183.3197 -    ko.virtualElements.allowedBindings['template'] = true;
183.3198 -})();
183.3199 -
183.3200 -ko.exportSymbol('setTemplateEngine', ko.setTemplateEngine);
183.3201 -ko.exportSymbol('renderTemplate', ko.renderTemplate);
183.3202 -
183.3203 -ko.utils.compareArrays = (function () {
183.3204 -    var statusNotInOld = 'added', statusNotInNew = 'deleted';
183.3205 -
183.3206 -    // Simple calculation based on Levenshtein distance.
183.3207 -    function compareArrays(oldArray, newArray, dontLimitMoves) {
183.3208 -        oldArray = oldArray || [];
183.3209 -        newArray = newArray || [];
183.3210 -
183.3211 -        if (oldArray.length <= newArray.length)
183.3212 -            return compareSmallArrayToBigArray(oldArray, newArray, statusNotInOld, statusNotInNew, dontLimitMoves);
183.3213 -        else
183.3214 -            return compareSmallArrayToBigArray(newArray, oldArray, statusNotInNew, statusNotInOld, dontLimitMoves);
183.3215 -    }
183.3216 -
183.3217 -    function compareSmallArrayToBigArray(smlArray, bigArray, statusNotInSml, statusNotInBig, dontLimitMoves) {
183.3218 -        var myMin = Math.min,
183.3219 -            myMax = Math.max,
183.3220 -            editDistanceMatrix = [],
183.3221 -            smlIndex, smlIndexMax = smlArray.length,
183.3222 -            bigIndex, bigIndexMax = bigArray.length,
183.3223 -            compareRange = (bigIndexMax - smlIndexMax) || 1,
183.3224 -            maxDistance = smlIndexMax + bigIndexMax + 1,
183.3225 -            thisRow, lastRow,
183.3226 -            bigIndexMaxForRow, bigIndexMinForRow;
183.3227 -
183.3228 -        for (smlIndex = 0; smlIndex <= smlIndexMax; smlIndex++) {
183.3229 -            lastRow = thisRow;
183.3230 -            editDistanceMatrix.push(thisRow = []);
183.3231 -            bigIndexMaxForRow = myMin(bigIndexMax, smlIndex + compareRange);
183.3232 -            bigIndexMinForRow = myMax(0, smlIndex - 1);
183.3233 -            for (bigIndex = bigIndexMinForRow; bigIndex <= bigIndexMaxForRow; bigIndex++) {
183.3234 -                if (!bigIndex)
183.3235 -                    thisRow[bigIndex] = smlIndex + 1;
183.3236 -                else if (!smlIndex)  // Top row - transform empty array into new array via additions
183.3237 -                    thisRow[bigIndex] = bigIndex + 1;
183.3238 -                else if (smlArray[smlIndex - 1] === bigArray[bigIndex - 1])
183.3239 -                    thisRow[bigIndex] = lastRow[bigIndex - 1];                  // copy value (no edit)
183.3240 -                else {
183.3241 -                    var northDistance = lastRow[bigIndex] || maxDistance;       // not in big (deletion)
183.3242 -                    var westDistance = thisRow[bigIndex - 1] || maxDistance;    // not in small (addition)
183.3243 -                    thisRow[bigIndex] = myMin(northDistance, westDistance) + 1;
183.3244 -                }
183.3245 -            }
183.3246 -        }
183.3247 -
183.3248 -        var editScript = [], meMinusOne, notInSml = [], notInBig = [];
183.3249 -        for (smlIndex = smlIndexMax, bigIndex = bigIndexMax; smlIndex || bigIndex;) {
183.3250 -            meMinusOne = editDistanceMatrix[smlIndex][bigIndex] - 1;
183.3251 -            if (bigIndex && meMinusOne === editDistanceMatrix[smlIndex][bigIndex-1]) {
183.3252 -                notInSml.push(editScript[editScript.length] = {     // added
183.3253 -                    'status': statusNotInSml,
183.3254 -                    'value': bigArray[--bigIndex],
183.3255 -                    'index': bigIndex });
183.3256 -            } else if (smlIndex && meMinusOne === editDistanceMatrix[smlIndex - 1][bigIndex]) {
183.3257 -                notInBig.push(editScript[editScript.length] = {     // deleted
183.3258 -                    'status': statusNotInBig,
183.3259 -                    'value': smlArray[--smlIndex],
183.3260 -                    'index': smlIndex });
183.3261 -            } else {
183.3262 -                editScript.push({
183.3263 -                    'status': "retained",
183.3264 -                    'value': bigArray[--bigIndex] });
183.3265 -                --smlIndex;
183.3266 -            }
183.3267 -        }
183.3268 -
183.3269 -        if (notInSml.length && notInBig.length) {
183.3270 -            // Set a limit on the number of consecutive non-matching comparisons; having it a multiple of
183.3271 -            // smlIndexMax keeps the time complexity of this algorithm linear.
183.3272 -            var limitFailedCompares = smlIndexMax * 10, failedCompares,
183.3273 -                a, d, notInSmlItem, notInBigItem;
183.3274 -            // Go through the items that have been added and deleted and try to find matches between them.
183.3275 -            for (failedCompares = a = 0; (dontLimitMoves || failedCompares < limitFailedCompares) && (notInSmlItem = notInSml[a]); a++) {
183.3276 -                for (d = 0; notInBigItem = notInBig[d]; d++) {
183.3277 -                    if (notInSmlItem['value'] === notInBigItem['value']) {
183.3278 -                        notInSmlItem['moved'] = notInBigItem['index'];
183.3279 -                        notInBigItem['moved'] = notInSmlItem['index'];
183.3280 -                        notInBig.splice(d,1);       // This item is marked as moved; so remove it from notInBig list
183.3281 -                        failedCompares = d = 0;     // Reset failed compares count because we're checking for consecutive failures
183.3282 -                        break;
183.3283 -                    }
183.3284 -                }
183.3285 -                failedCompares += d;
183.3286 -            }
183.3287 -        }
183.3288 -        return editScript.reverse();
183.3289 -    }
183.3290 -
183.3291 -    return compareArrays;
183.3292 -})();
183.3293 -
183.3294 -ko.exportSymbol('utils.compareArrays', ko.utils.compareArrays);
183.3295 -
183.3296 -(function () {
183.3297 -    // Objective:
183.3298 -    // * Given an input array, a container DOM node, and a function from array elements to arrays of DOM nodes,
183.3299 -    //   map the array elements to arrays of DOM nodes, concatenate together all these arrays, and use them to populate the container DOM node
183.3300 -    // * Next time we're given the same combination of things (with the array possibly having mutated), update the container DOM node
183.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
183.3302 -    //   previously mapped - retain those nodes, and just insert/delete other ones
183.3303 -
183.3304 -    // "callbackAfterAddingNodes" will be invoked after any "mapping"-generated nodes are inserted into the container node
183.3305 -    // You can use this, for example, to activate bindings on those nodes.
183.3306 -
183.3307 -    function fixUpNodesToBeMovedOrRemoved(contiguousNodeArray) {
183.3308 -        // Before moving, deleting, or replacing a set of nodes that were previously outputted by the "map" function, we have to reconcile
183.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,
183.3310 -        // or that new nodes might have been inserted in the middle, for example by a binding. Also, there may previously have been
183.3311 -        // leading comment nodes (created by rewritten string-based templates) that have since been removed during binding.
183.3312 -        // So, this function translates the old "map" output array into its best guess of what set of current DOM nodes should be removed.
183.3313 -        //
183.3314 -        // Rules:
183.3315 -        //   [A] Any leading nodes that aren't in the document any more should be ignored
183.3316 -        //       These most likely correspond to memoization nodes that were already removed during binding
183.3317 -        //       See https://github.com/SteveSanderson/knockout/pull/440
183.3318 -        //   [B] We want to output a contiguous series of nodes that are still in the document. So, ignore any nodes that
183.3319 -        //       have already been removed, and include any nodes that have been inserted among the previous collection
183.3320 -
183.3321 -        // Rule [A]
183.3322 -        while (contiguousNodeArray.length && !ko.utils.domNodeIsAttachedToDocument(contiguousNodeArray[0]))
183.3323 -            contiguousNodeArray.splice(0, 1);
183.3324 -
183.3325 -        // Rule [B]
183.3326 -        if (contiguousNodeArray.length > 1) {
183.3327 -            // Build up the actual new contiguous node set
183.3328 -            var current = contiguousNodeArray[0], last = contiguousNodeArray[contiguousNodeArray.length - 1], newContiguousSet = [current];
183.3329 -            while (current !== last) {
183.3330 -                current = current.nextSibling;
183.3331 -                if (!current) // Won't happen, except if the developer has manually removed some DOM elements (then we're in an undefined scenario)
183.3332 -                    return;
183.3333 -                newContiguousSet.push(current);
183.3334 -            }
183.3335 -
183.3336 -            // ... then mutate the input array to match this.
183.3337 -            // (The following line replaces the contents of contiguousNodeArray with newContiguousSet)
183.3338 -            Array.prototype.splice.apply(contiguousNodeArray, [0, contiguousNodeArray.length].concat(newContiguousSet));
183.3339 -        }
183.3340 -        return contiguousNodeArray;
183.3341 -    }
183.3342 -
183.3343 -    function mapNodeAndRefreshWhenChanged(containerNode, mapping, valueToMap, callbackAfterAddingNodes, index) {
183.3344 -        // Map this array value inside a dependentObservable so we re-map when any dependency changes
183.3345 -        var mappedNodes = [];
183.3346 -        var dependentObservable = ko.dependentObservable(function() {
183.3347 -            var newMappedNodes = mapping(valueToMap, index) || [];
183.3348 -
183.3349 -            // On subsequent evaluations, just replace the previously-inserted DOM nodes
183.3350 -            if (mappedNodes.length > 0) {
183.3351 -                ko.utils.replaceDomNodes(fixUpNodesToBeMovedOrRemoved(mappedNodes), newMappedNodes);
183.3352 -                if (callbackAfterAddingNodes)
183.3353 -                    ko.dependencyDetection.ignore(callbackAfterAddingNodes, null, [valueToMap, newMappedNodes, index]);
183.3354 -            }
183.3355 -
183.3356 -            // Replace the contents of the mappedNodes array, thereby updating the record
183.3357 -            // of which nodes would be deleted if valueToMap was itself later removed
183.3358 -            mappedNodes.splice(0, mappedNodes.length);
183.3359 -            ko.utils.arrayPushAll(mappedNodes, newMappedNodes);
183.3360 -        }, null, { disposeWhenNodeIsRemoved: containerNode, disposeWhen: function() { return (mappedNodes.length == 0) || !ko.utils.domNodeIsAttachedToDocument(mappedNodes[0]) } });
183.3361 -        return { mappedNodes : mappedNodes, dependentObservable : (dependentObservable.isActive() ? dependentObservable : undefined) };
183.3362 -    }
183.3363 -
183.3364 -    var lastMappingResultDomDataKey = "setDomNodeChildrenFromArrayMapping_lastMappingResult";
183.3365 -
183.3366 -    ko.utils.setDomNodeChildrenFromArrayMapping = function (domNode, array, mapping, options, callbackAfterAddingNodes) {
183.3367 -        // Compare the provided array against the previous one
183.3368 -        array = array || [];
183.3369 -        options = options || {};
183.3370 -        var isFirstExecution = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) === undefined;
183.3371 -        var lastMappingResult = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) || [];
183.3372 -        var lastArray = ko.utils.arrayMap(lastMappingResult, function (x) { return x.arrayEntry; });
183.3373 -        var editScript = ko.utils.compareArrays(lastArray, array);
183.3374 -
183.3375 -        // Build the new mapping result
183.3376 -        var newMappingResult = [];
183.3377 -        var lastMappingResultIndex = 0;
183.3378 -        var newMappingResultIndex = 0;
183.3379 -
183.3380 -        var nodesToDelete = [];
183.3381 -        var itemsToProcess = [];
183.3382 -        var itemsForBeforeRemoveCallbacks = [];
183.3383 -        var itemsForMoveCallbacks = [];
183.3384 -        var itemsForAfterAddCallbacks = [];
183.3385 -        var mapData;
183.3386 -
183.3387 -        function itemMovedOrRetained(editScriptIndex, oldPosition) {
183.3388 -            mapData = lastMappingResult[oldPosition];
183.3389 -            if (newMappingResultIndex !== oldPosition)
183.3390 -                itemsForMoveCallbacks[editScriptIndex] = mapData;
183.3391 -            // Since updating the index might change the nodes, do so before calling fixUpNodesToBeMovedOrRemoved
183.3392 -            mapData.indexObservable(newMappingResultIndex++);
183.3393 -            fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes);
183.3394 -            newMappingResult.push(mapData);
183.3395 -            itemsToProcess.push(mapData);
183.3396 -        }
183.3397 -
183.3398 -        function callCallback(callback, items) {
183.3399 -            if (callback) {
183.3400 -                for (var i = 0, n = items.length; i < n; i++) {
183.3401 -                    if (items[i]) {
183.3402 -                        ko.utils.arrayForEach(items[i].mappedNodes, function(node) {
183.3403 -                            callback(node, i, items[i].arrayEntry);
183.3404 -                        });
183.3405 -                    }
183.3406 -                }
183.3407 -            }
183.3408 -        }
183.3409 -
183.3410 -        for (var i = 0, editScriptItem, movedIndex; editScriptItem = editScript[i]; i++) {
183.3411 -            movedIndex = editScriptItem['moved'];
183.3412 -            switch (editScriptItem['status']) {
183.3413 -                case "deleted":
183.3414 -                    if (movedIndex === undefined) {
183.3415 -                        mapData = lastMappingResult[lastMappingResultIndex];
183.3416 -
183.3417 -                        // Stop tracking changes to the mapping for these nodes
183.3418 -                        if (mapData.dependentObservable)
183.3419 -                            mapData.dependentObservable.dispose();
183.3420 -
183.3421 -                        // Queue these nodes for later removal
183.3422 -                        nodesToDelete.push.apply(nodesToDelete, fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes));
183.3423 -                        if (options['beforeRemove']) {
183.3424 -                            itemsForBeforeRemoveCallbacks[i] = mapData;
183.3425 -                            itemsToProcess.push(mapData);
183.3426 -                        }
183.3427 -                    }
183.3428 -                    lastMappingResultIndex++;
183.3429 -                    break;
183.3430 -
183.3431 -                case "retained":
183.3432 -                    itemMovedOrRetained(i, lastMappingResultIndex++);
183.3433 -                    break;
183.3434 -
183.3435 -                case "added":
183.3436 -                    if (movedIndex !== undefined) {
183.3437 -                        itemMovedOrRetained(i, movedIndex);
183.3438 -                    } else {
183.3439 -                        mapData = { arrayEntry: editScriptItem['value'], indexObservable: ko.observable(newMappingResultIndex++) };
183.3440 -                        newMappingResult.push(mapData);
183.3441 -                        itemsToProcess.push(mapData);
183.3442 -                        if (!isFirstExecution)
183.3443 -                            itemsForAfterAddCallbacks[i] = mapData;
183.3444 -                    }
183.3445 -                    break;
183.3446 -            }
183.3447 -        }
183.3448 -
183.3449 -        // Call beforeMove first before any changes have been made to the DOM
183.3450 -        callCallback(options['beforeMove'], itemsForMoveCallbacks);
183.3451 -
183.3452 -        // Next remove nodes for deleted items (or just clean if there's a beforeRemove callback)
183.3453 -        ko.utils.arrayForEach(nodesToDelete, options['beforeRemove'] ? ko.cleanNode : ko.removeNode);
183.3454 -
183.3455 -        // Next add/reorder the remaining items (will include deleted items if there's a beforeRemove callback)
183.3456 -        for (var i = 0, nextNode = ko.virtualElements.firstChild(domNode), lastNode, node; mapData = itemsToProcess[i]; i++) {
183.3457 -            // Get nodes for newly added items
183.3458 -            if (!mapData.mappedNodes)
183.3459 -                ko.utils.extend(mapData, mapNodeAndRefreshWhenChanged(domNode, mapping, mapData.arrayEntry, callbackAfterAddingNodes, mapData.indexObservable));
183.3460 -
183.3461 -            // Put nodes in the right place if they aren't there already
183.3462 -            for (var j = 0; node = mapData.mappedNodes[j]; nextNode = node.nextSibling, lastNode = node, j++) {
183.3463 -                if (node !== nextNode)
183.3464 -                    ko.virtualElements.insertAfter(domNode, node, lastNode);
183.3465 -            }
183.3466 -
183.3467 -            // Run the callbacks for newly added nodes (for example, to apply bindings, etc.)
183.3468 -            if (!mapData.initialized && callbackAfterAddingNodes) {
183.3469 -                callbackAfterAddingNodes(mapData.arrayEntry, mapData.mappedNodes, mapData.indexObservable);
183.3470 -                mapData.initialized = true;
183.3471 -            }
183.3472 -        }
183.3473 -
183.3474 -        // If there's a beforeRemove callback, call it after reordering.
183.3475 -        // Note that we assume that the beforeRemove callback will usually be used to remove the nodes using
183.3476 -        // some sort of animation, which is why we first reorder the nodes that will be removed. If the
183.3477 -        // callback instead removes the nodes right away, it would be more efficient to skip reordering them.
183.3478 -        // Perhaps we'll make that change in the future if this scenario becomes more common.
183.3479 -        callCallback(options['beforeRemove'], itemsForBeforeRemoveCallbacks);
183.3480 -
183.3481 -        // Finally call afterMove and afterAdd callbacks
183.3482 -        callCallback(options['afterMove'], itemsForMoveCallbacks);
183.3483 -        callCallback(options['afterAdd'], itemsForAfterAddCallbacks);
183.3484 -
183.3485 -        // Store a copy of the array items we just considered so we can difference it next time
183.3486 -        ko.utils.domData.set(domNode, lastMappingResultDomDataKey, newMappingResult);
183.3487 -    }
183.3488 -})();
183.3489 -
183.3490 -ko.exportSymbol('utils.setDomNodeChildrenFromArrayMapping', ko.utils.setDomNodeChildrenFromArrayMapping);
183.3491 -ko.nativeTemplateEngine = function () {
183.3492 -    this['allowTemplateRewriting'] = false;
183.3493 -}
183.3494 -
183.3495 -ko.nativeTemplateEngine.prototype = new ko.templateEngine();
183.3496 -ko.nativeTemplateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
183.3497 -    var useNodesIfAvailable = !(ko.utils.ieVersion < 9), // IE<9 cloneNode doesn't work properly
183.3498 -        templateNodesFunc = useNodesIfAvailable ? templateSource['nodes'] : null,
183.3499 -        templateNodes = templateNodesFunc ? templateSource['nodes']() : null;
183.3500 -
183.3501 -    if (templateNodes) {
183.3502 -        return ko.utils.makeArray(templateNodes.cloneNode(true).childNodes);
183.3503 -    } else {
183.3504 -        var templateText = templateSource['text']();
183.3505 -        return ko.utils.parseHtmlFragment(templateText);
183.3506 -    }
183.3507 -};
183.3508 -
183.3509 -ko.nativeTemplateEngine.instance = new ko.nativeTemplateEngine();
183.3510 -ko.setTemplateEngine(ko.nativeTemplateEngine.instance);
183.3511 -
183.3512 -ko.exportSymbol('nativeTemplateEngine', ko.nativeTemplateEngine);
183.3513 -(function() {
183.3514 -    ko.jqueryTmplTemplateEngine = function () {
183.3515 -        // Detect which version of jquery-tmpl you're using. Unfortunately jquery-tmpl
183.3516 -        // doesn't expose a version number, so we have to infer it.
183.3517 -        // Note that as of Knockout 1.3, we only support jQuery.tmpl 1.0.0pre and later,
183.3518 -        // which KO internally refers to as version "2", so older versions are no longer detected.
183.3519 -        var jQueryTmplVersion = this.jQueryTmplVersion = (function() {
183.3520 -            if ((typeof(jQuery) == "undefined") || !(jQuery['tmpl']))
183.3521 -                return 0;
183.3522 -            // Since it exposes no official version number, we use our own numbering system. To be updated as jquery-tmpl evolves.
183.3523 -            try {
183.3524 -                if (jQuery['tmpl']['tag']['tmpl']['open'].toString().indexOf('__') >= 0) {
183.3525 -                    // Since 1.0.0pre, custom tags should append markup to an array called "__"
183.3526 -                    return 2; // Final version of jquery.tmpl
183.3527 -                }
183.3528 -            } catch(ex) { /* Apparently not the version we were looking for */ }
183.3529 -
183.3530 -            return 1; // Any older version that we don't support
183.3531 -        })();
183.3532 -
183.3533 -        function ensureHasReferencedJQueryTemplates() {
183.3534 -            if (jQueryTmplVersion < 2)
183.3535 -                throw new Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");
183.3536 -        }
183.3537 -
183.3538 -        function executeTemplate(compiledTemplate, data, jQueryTemplateOptions) {
183.3539 -            return jQuery['tmpl'](compiledTemplate, data, jQueryTemplateOptions);
183.3540 -        }
183.3541 -
183.3542 -        this['renderTemplateSource'] = function(templateSource, bindingContext, options) {
183.3543 -            options = options || {};
183.3544 -            ensureHasReferencedJQueryTemplates();
183.3545 -
183.3546 -            // Ensure we have stored a precompiled version of this template (don't want to reparse on every render)
183.3547 -            var precompiled = templateSource['data']('precompiled');
183.3548 -            if (!precompiled) {
183.3549 -                var templateText = templateSource['text']() || "";
183.3550 -                // Wrap in "with($whatever.koBindingContext) { ... }"
183.3551 -                templateText = "{{ko_with $item.koBindingContext}}" + templateText + "{{/ko_with}}";
183.3552 -
183.3553 -                precompiled = jQuery['template'](null, templateText);
183.3554 -                templateSource['data']('precompiled', precompiled);
183.3555 -            }
183.3556 -
183.3557 -            var data = [bindingContext['$data']]; // Prewrap the data in an array to stop jquery.tmpl from trying to unwrap any arrays
183.3558 -            var jQueryTemplateOptions = jQuery['extend']({ 'koBindingContext': bindingContext }, options['templateOptions']);
183.3559 -
183.3560 -            var resultNodes = executeTemplate(precompiled, data, jQueryTemplateOptions);
183.3561 -            resultNodes['appendTo'](document.createElement("div")); // Using "appendTo" forces jQuery/jQuery.tmpl to perform necessary cleanup work
183.3562 -
183.3563 -            jQuery['fragments'] = {}; // Clear jQuery's fragment cache to avoid a memory leak after a large number of template renders
183.3564 -            return resultNodes;
183.3565 -        };
183.3566 -
183.3567 -        this['createJavaScriptEvaluatorBlock'] = function(script) {
183.3568 -            return "{{ko_code ((function() { return " + script + " })()) }}";
183.3569 -        };
183.3570 -
183.3571 -        this['addTemplate'] = function(templateName, templateMarkup) {
183.3572 -            document.write("<script type='text/html' id='" + templateName + "'>" + templateMarkup + "</script>");
183.3573 -        };
183.3574 -
183.3575 -        if (jQueryTmplVersion > 0) {
183.3576 -            jQuery['tmpl']['tag']['ko_code'] = {
183.3577 -                open: "__.push($1 || '');"
183.3578 -            };
183.3579 -            jQuery['tmpl']['tag']['ko_with'] = {
183.3580 -                open: "with($1) {",
183.3581 -                close: "} "
183.3582 -            };
183.3583 -        }
183.3584 -    };
183.3585 -
183.3586 -    ko.jqueryTmplTemplateEngine.prototype = new ko.templateEngine();
183.3587 -
183.3588 -    // Use this one by default *only if jquery.tmpl is referenced*
183.3589 -    var jqueryTmplTemplateEngineInstance = new ko.jqueryTmplTemplateEngine();
183.3590 -    if (jqueryTmplTemplateEngineInstance.jQueryTmplVersion > 0)
183.3591 -        ko.setTemplateEngine(jqueryTmplTemplateEngineInstance);
183.3592 -
183.3593 -    ko.exportSymbol('jqueryTmplTemplateEngine', ko.jqueryTmplTemplateEngine);
183.3594 -})();
183.3595 -});
183.3596 -})(window,document,navigator,window["jQuery"]);
183.3597 -})();
183.3598 \ No newline at end of file
   184.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   184.2 +++ b/ko-fx/src/main/resources/org/netbeans/html/kofx/knockout-2.2.1.js	Mon Dec 16 17:16:40 2013 +0100
   184.3 @@ -0,0 +1,3594 @@
   184.4 +// Knockout JavaScript library v2.2.1
   184.5 +// (c) Steven Sanderson - http://knockoutjs.com/
   184.6 +// License: MIT (http://www.opensource.org/licenses/mit-license.php)
   184.7 +
   184.8 +(function(){
   184.9 +var DEBUG=true;
  184.10 +(function(window,document,navigator,jQuery,undefined){
  184.11 +!function(factory) {
  184.12 +    // Support three module loading scenarios
  184.13 +    if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
  184.14 +        // [1] CommonJS/Node.js
  184.15 +        var target = module['exports'] || exports; // module.exports is for Node.js
  184.16 +        factory(target);
  184.17 +    } else if (typeof define === 'function' && define['amd']) {
  184.18 +        // [2] AMD anonymous module
  184.19 +        define(['exports'], factory);
  184.20 +    } else {
  184.21 +        // [3] No module loader (plain <script> tag) - put directly in global namespace
  184.22 +        factory(window['ko'] = {});
  184.23 +    }
  184.24 +}(function(koExports){
  184.25 +// Internally, all KO objects are attached to koExports (even the non-exported ones whose names will be minified by the closure compiler).
  184.26 +// In the future, the following "ko" variable may be made distinct from "koExports" so that private objects are not externally reachable.
  184.27 +var ko = typeof koExports !== 'undefined' ? koExports : {};
  184.28 +// Google Closure Compiler helpers (used only to make the minified file smaller)
  184.29 +ko.exportSymbol = function(koPath, object) {
  184.30 +	var tokens = koPath.split(".");
  184.31 +
  184.32 +	// In the future, "ko" may become distinct from "koExports" (so that non-exported objects are not reachable)
  184.33 +	// At that point, "target" would be set to: (typeof koExports !== "undefined" ? koExports : ko)
  184.34 +	var target = ko;
  184.35 +
  184.36 +	for (var i = 0; i < tokens.length - 1; i++)
  184.37 +		target = target[tokens[i]];
  184.38 +	target[tokens[tokens.length - 1]] = object;
  184.39 +};
  184.40 +ko.exportProperty = function(owner, publicName, object) {
  184.41 +  owner[publicName] = object;
  184.42 +};
  184.43 +ko.version = "2.2.1";
  184.44 +
  184.45 +ko.exportSymbol('version', ko.version);
  184.46 +ko.utils = new (function () {
  184.47 +    var stringTrimRegex = /^(\s|\u00A0)+|(\s|\u00A0)+$/g;
  184.48 +
  184.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)
  184.50 +    var knownEvents = {}, knownEventTypesByEventName = {};
  184.51 +    var keyEventTypeName = /Firefox\/2/i.test(navigator.userAgent) ? 'KeyboardEvent' : 'UIEvents';
  184.52 +    knownEvents[keyEventTypeName] = ['keyup', 'keydown', 'keypress'];
  184.53 +    knownEvents['MouseEvents'] = ['click', 'dblclick', 'mousedown', 'mouseup', 'mousemove', 'mouseover', 'mouseout', 'mouseenter', 'mouseleave'];
  184.54 +    for (var eventType in knownEvents) {
  184.55 +        var knownEventsForType = knownEvents[eventType];
  184.56 +        if (knownEventsForType.length) {
  184.57 +            for (var i = 0, j = knownEventsForType.length; i < j; i++)
  184.58 +                knownEventTypesByEventName[knownEventsForType[i]] = eventType;
  184.59 +        }
  184.60 +    }
  184.61 +    var eventsThatMustBeRegisteredUsingAttachEvent = { 'propertychange': true }; // Workaround for an IE9 issue - https://github.com/SteveSanderson/knockout/issues/406
  184.62 +
  184.63 +    // Detect IE versions for bug workarounds (uses IE conditionals, not UA string, for robustness)
  184.64 +    // Note that, since IE 10 does not support conditional comments, the following logic only detects IE < 10.
  184.65 +    // Currently this is by design, since IE 10+ behaves correctly when treated as a standard browser.
  184.66 +    // If there is a future need to detect specific versions of IE10+, we will amend this.
  184.67 +    var ieVersion = (function() {
  184.68 +        var version = 3, div = document.createElement('div'), iElems = div.getElementsByTagName('i');
  184.69 +
  184.70 +        // Keep constructing conditional HTML blocks until we hit one that resolves to an empty fragment
  184.71 +        while (
  184.72 +            div.innerHTML = '<!--[if gt IE ' + (++version) + ']><i></i><![endif]-->',
  184.73 +            iElems[0]
  184.74 +        );
  184.75 +        return version > 4 ? version : undefined;
  184.76 +    }());
  184.77 +    var isIe6 = ieVersion === 6,
  184.78 +        isIe7 = ieVersion === 7;
  184.79 +
  184.80 +    function isClickOnCheckableElement(element, eventType) {
  184.81 +        if ((ko.utils.tagNameLower(element) !== "input") || !element.type) return false;
  184.82 +        if (eventType.toLowerCase() != "click") return false;
  184.83 +        var inputType = element.type;
  184.84 +        return (inputType == "checkbox") || (inputType == "radio");
  184.85 +    }
  184.86 +
  184.87 +    return {
  184.88 +        fieldsIncludedWithJsonPost: ['authenticity_token', /^__RequestVerificationToken(_.*)?$/],
  184.89 +
  184.90 +        arrayForEach: function (array, action) {
  184.91 +            for (var i = 0, j = array.length; i < j; i++)
  184.92 +                action(array[i]);
  184.93 +        },
  184.94 +
  184.95 +        arrayIndexOf: function (array, item) {
  184.96 +            if (typeof Array.prototype.indexOf == "function")
  184.97 +                return Array.prototype.indexOf.call(array, item);
  184.98 +            for (var i = 0, j = array.length; i < j; i++)
  184.99 +                if (array[i] === item)
 184.100 +                    return i;
 184.101 +            return -1;
 184.102 +        },
 184.103 +
 184.104 +        arrayFirst: function (array, predicate, predicateOwner) {
 184.105 +            for (var i = 0, j = array.length; i < j; i++)
 184.106 +                if (predicate.call(predicateOwner, array[i]))
 184.107 +                    return array[i];
 184.108 +            return null;
 184.109 +        },
 184.110 +
 184.111 +        arrayRemoveItem: function (array, itemToRemove) {
 184.112 +            var index = ko.utils.arrayIndexOf(array, itemToRemove);
 184.113 +            if (index >= 0)
 184.114 +                array.splice(index, 1);
 184.115 +        },
 184.116 +
 184.117 +        arrayGetDistinctValues: function (array) {
 184.118 +            array = array || [];
 184.119 +            var result = [];
 184.120 +            for (var i = 0, j = array.length; i < j; i++) {
 184.121 +                if (ko.utils.arrayIndexOf(result, array[i]) < 0)
 184.122 +                    result.push(array[i]);
 184.123 +            }
 184.124 +            return result;
 184.125 +        },
 184.126 +
 184.127 +        arrayMap: function (array, mapping) {
 184.128 +            array = array || [];
 184.129 +            var result = [];
 184.130 +            for (var i = 0, j = array.length; i < j; i++)
 184.131 +                result.push(mapping(array[i]));
 184.132 +            return result;
 184.133 +        },
 184.134 +
 184.135 +        arrayFilter: function (array, predicate) {
 184.136 +            array = array || [];
 184.137 +            var result = [];
 184.138 +            for (var i = 0, j = array.length; i < j; i++)
 184.139 +                if (predicate(array[i]))
 184.140 +                    result.push(array[i]);
 184.141 +            return result;
 184.142 +        },
 184.143 +
 184.144 +        arrayPushAll: function (array, valuesToPush) {
 184.145 +            if (valuesToPush instanceof Array)
 184.146 +                array.push.apply(array, valuesToPush);
 184.147 +            else
 184.148 +                for (var i = 0, j = valuesToPush.length; i < j; i++)
 184.149 +                    array.push(valuesToPush[i]);
 184.150 +            return array;
 184.151 +        },
 184.152 +
 184.153 +        extend: function (target, source) {
 184.154 +            if (source) {
 184.155 +                for(var prop in source) {
 184.156 +                    if(source.hasOwnProperty(prop)) {
 184.157 +                        target[prop] = source[prop];
 184.158 +                    }
 184.159 +                }
 184.160 +            }
 184.161 +            return target;
 184.162 +        },
 184.163 +
 184.164 +        emptyDomNode: function (domNode) {
 184.165 +            while (domNode.firstChild) {
 184.166 +                ko.removeNode(domNode.firstChild);
 184.167 +            }
 184.168 +        },
 184.169 +
 184.170 +        moveCleanedNodesToContainerElement: function(nodes) {
 184.171 +            // Ensure it's a real array, as we're about to reparent the nodes and
 184.172 +            // we don't want the underlying collection to change while we're doing that.
 184.173 +            var nodesArray = ko.utils.makeArray(nodes);
 184.174 +
 184.175 +            var container = document.createElement('div');
 184.176 +            for (var i = 0, j = nodesArray.length; i < j; i++) {
 184.177 +                container.appendChild(ko.cleanNode(nodesArray[i]));
 184.178 +            }
 184.179 +            return container;
 184.180 +        },
 184.181 +
 184.182 +        cloneNodes: function (nodesArray, shouldCleanNodes) {
 184.183 +            for (var i = 0, j = nodesArray.length, newNodesArray = []; i < j; i++) {
 184.184 +                var clonedNode = nodesArray[i].cloneNode(true);
 184.185 +                newNodesArray.push(shouldCleanNodes ? ko.cleanNode(clonedNode) : clonedNode);
 184.186 +            }
 184.187 +            return newNodesArray;
 184.188 +        },
 184.189 +
 184.190 +        setDomNodeChildren: function (domNode, childNodes) {
 184.191 +            ko.utils.emptyDomNode(domNode);
 184.192 +            if (childNodes) {
 184.193 +                for (var i = 0, j = childNodes.length; i < j; i++)
 184.194 +                    domNode.appendChild(childNodes[i]);
 184.195 +            }
 184.196 +        },
 184.197 +
 184.198 +        replaceDomNodes: function (nodeToReplaceOrNodeArray, newNodesArray) {
 184.199 +            var nodesToReplaceArray = nodeToReplaceOrNodeArray.nodeType ? [nodeToReplaceOrNodeArray] : nodeToReplaceOrNodeArray;
 184.200 +            if (nodesToReplaceArray.length > 0) {
 184.201 +                var insertionPoint = nodesToReplaceArray[0];
 184.202 +                var parent = insertionPoint.parentNode;
 184.203 +                for (var i = 0, j = newNodesArray.length; i < j; i++)
 184.204 +                    parent.insertBefore(newNodesArray[i], insertionPoint);
 184.205 +                for (var i = 0, j = nodesToReplaceArray.length; i < j; i++) {
 184.206 +                    ko.removeNode(nodesToReplaceArray[i]);
 184.207 +                }
 184.208 +            }
 184.209 +        },
 184.210 +
 184.211 +        setOptionNodeSelectionState: function (optionNode, isSelected) {
 184.212 +            // IE6 sometimes throws "unknown error" if you try to write to .selected directly, whereas Firefox struggles with setAttribute. Pick one based on browser.
 184.213 +            if (ieVersion < 7)
 184.214 +                optionNode.setAttribute("selected", isSelected);
 184.215 +            else
 184.216 +                optionNode.selected = isSelected;
 184.217 +        },
 184.218 +
 184.219 +        stringTrim: function (string) {
 184.220 +            return (string || "").replace(stringTrimRegex, "");
 184.221 +        },
 184.222 +
 184.223 +        stringTokenize: function (string, delimiter) {
 184.224 +            var result = [];
 184.225 +            var tokens = (string || "").split(delimiter);
 184.226 +            for (var i = 0, j = tokens.length; i < j; i++) {
 184.227 +                var trimmed = ko.utils.stringTrim(tokens[i]);
 184.228 +                if (trimmed !== "")
 184.229 +                    result.push(trimmed);
 184.230 +            }
 184.231 +            return result;
 184.232 +        },
 184.233 +
 184.234 +        stringStartsWith: function (string, startsWith) {
 184.235 +            string = string || "";
 184.236 +            if (startsWith.length > string.length)
 184.237 +                return false;
 184.238 +            return string.substring(0, startsWith.length) === startsWith;
 184.239 +        },
 184.240 +
 184.241 +        domNodeIsContainedBy: function (node, containedByNode) {
 184.242 +            if (containedByNode.compareDocumentPosition)
 184.243 +                return (containedByNode.compareDocumentPosition(node) & 16) == 16;
 184.244 +            while (node != null) {
 184.245 +                if (node == containedByNode)
 184.246 +                    return true;
 184.247 +                node = node.parentNode;
 184.248 +            }
 184.249 +            return false;
 184.250 +        },
 184.251 +
 184.252 +        domNodeIsAttachedToDocument: function (node) {
 184.253 +            return ko.utils.domNodeIsContainedBy(node, node.ownerDocument);
 184.254 +        },
 184.255 +
 184.256 +        tagNameLower: function(element) {
 184.257 +            // For HTML elements, tagName will always be upper case; for XHTML elements, it'll be lower case.
 184.258 +            // Possible future optimization: If we know it's an element from an XHTML document (not HTML),
 184.259 +            // we don't need to do the .toLowerCase() as it will always be lower case anyway.
 184.260 +            return element && element.tagName && element.tagName.toLowerCase();
 184.261 +        },
 184.262 +
 184.263 +        registerEventHandler: function (element, eventType, handler) {
 184.264 +            var mustUseAttachEvent = ieVersion && eventsThatMustBeRegisteredUsingAttachEvent[eventType];
 184.265 +            if (!mustUseAttachEvent && typeof jQuery != "undefined") {
 184.266 +                if (isClickOnCheckableElement(element, eventType)) {
 184.267 +                    // For click events on checkboxes, jQuery interferes with the event handling in an awkward way:
 184.268 +                    // it toggles the element checked state *after* the click event handlers run, whereas native
 184.269 +                    // click events toggle the checked state *before* the event handler.
 184.270 +                    // Fix this by intecepting the handler and applying the correct checkedness before it runs.
 184.271 +                    var originalHandler = handler;
 184.272 +                    handler = function(event, eventData) {
 184.273 +                        var jQuerySuppliedCheckedState = this.checked;
 184.274 +                        if (eventData)
 184.275 +                            this.checked = eventData.checkedStateBeforeEvent !== true;
 184.276 +                        originalHandler.call(this, event);
 184.277 +                        this.checked = jQuerySuppliedCheckedState; // Restore the state jQuery applied
 184.278 +                    };
 184.279 +                }
 184.280 +                jQuery(element)['bind'](eventType, handler);
 184.281 +            } else if (!mustUseAttachEvent && typeof element.addEventListener == "function")
 184.282 +                element.addEventListener(eventType, handler, false);
 184.283 +            else if (typeof element.attachEvent != "undefined")
 184.284 +                element.attachEvent("on" + eventType, function (event) {
 184.285 +                    handler.call(element, event);
 184.286 +                });
 184.287 +            else
 184.288 +                throw new Error("Browser doesn't support addEventListener or attachEvent");
 184.289 +        },
 184.290 +
 184.291 +        triggerEvent: function (element, eventType) {
 184.292 +            if (!(element && element.nodeType))
 184.293 +                throw new Error("element must be a DOM node when calling triggerEvent");
 184.294 +
 184.295 +            if (typeof jQuery != "undefined") {
 184.296 +                var eventData = [];
 184.297 +                if (isClickOnCheckableElement(element, eventType)) {
 184.298 +                    // Work around the jQuery "click events on checkboxes" issue described above by storing the original checked state before triggering the handler
 184.299 +                    eventData.push({ checkedStateBeforeEvent: element.checked });
 184.300 +                }
 184.301 +                jQuery(element)['trigger'](eventType, eventData);
 184.302 +            } else if (typeof document.createEvent == "function") {
 184.303 +                if (typeof element.dispatchEvent == "function") {
 184.304 +                    var eventCategory = knownEventTypesByEventName[eventType] || "HTMLEvents";
 184.305 +                    var event = document.createEvent(eventCategory);
 184.306 +                    event.initEvent(eventType, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, element);
 184.307 +                    element.dispatchEvent(event);
 184.308 +                }
 184.309 +                else
 184.310 +                    throw new Error("The supplied element doesn't support dispatchEvent");
 184.311 +            } else if (typeof element.fireEvent != "undefined") {
 184.312 +                // Unlike other browsers, IE doesn't change the checked state of checkboxes/radiobuttons when you trigger their "click" event
 184.313 +                // so to make it consistent, we'll do it manually here
 184.314 +                if (isClickOnCheckableElement(element, eventType))
 184.315 +                    element.checked = element.checked !== true;
 184.316 +                element.fireEvent("on" + eventType);
 184.317 +            }
 184.318 +            else
 184.319 +                throw new Error("Browser doesn't support triggering events");
 184.320 +        },
 184.321 +
 184.322 +        unwrapObservable: function (value) {
 184.323 +            return ko.isObservable(value) ? value() : value;
 184.324 +        },
 184.325 +
 184.326 +        peekObservable: function (value) {
 184.327 +            return ko.isObservable(value) ? value.peek() : value;
 184.328 +        },
 184.329 +
 184.330 +        toggleDomNodeCssClass: function (node, classNames, shouldHaveClass) {
 184.331 +            if (classNames) {
 184.332 +                var cssClassNameRegex = /[\w-]+/g,
 184.333 +                    currentClassNames = node.className.match(cssClassNameRegex) || [];
 184.334 +                ko.utils.arrayForEach(classNames.match(cssClassNameRegex), function(className) {
 184.335 +                    var indexOfClass = ko.utils.arrayIndexOf(currentClassNames, className);
 184.336 +                    if (indexOfClass >= 0) {
 184.337 +                        if (!shouldHaveClass)
 184.338 +                            currentClassNames.splice(indexOfClass, 1);
 184.339 +                    } else {
 184.340 +                        if (shouldHaveClass)
 184.341 +                            currentClassNames.push(className);
 184.342 +                    }
 184.343 +                });
 184.344 +                node.className = currentClassNames.join(" ");
 184.345 +            }
 184.346 +        },
 184.347 +
 184.348 +        setTextContent: function(element, textContent) {
 184.349 +            var value = ko.utils.unwrapObservable(textContent);
 184.350 +            if ((value === null) || (value === undefined))
 184.351 +                value = "";
 184.352 +
 184.353 +            if (element.nodeType === 3) {
 184.354 +                element.data = value;
 184.355 +            } else {
 184.356 +                // We need there to be exactly one child: a text node.
 184.357 +                // If there are no children, more than one, or if it's not a text node,
 184.358 +                // we'll clear everything and create a single text node.
 184.359 +                var innerTextNode = ko.virtualElements.firstChild(element);
 184.360 +                if (!innerTextNode || innerTextNode.nodeType != 3 || ko.virtualElements.nextSibling(innerTextNode)) {
 184.361 +                    ko.virtualElements.setDomNodeChildren(element, [document.createTextNode(value)]);
 184.362 +                } else {
 184.363 +                    innerTextNode.data = value;
 184.364 +                }
 184.365 +
 184.366 +                ko.utils.forceRefresh(element);
 184.367 +            }
 184.368 +        },
 184.369 +
 184.370 +        setElementName: function(element, name) {
 184.371 +            element.name = name;
 184.372 +
 184.373 +            // Workaround IE 6/7 issue
 184.374 +            // - https://github.com/SteveSanderson/knockout/issues/197
 184.375 +            // - http://www.matts411.com/post/setting_the_name_attribute_in_ie_dom/
 184.376 +            if (ieVersion <= 7) {
 184.377 +                try {
 184.378 +                    element.mergeAttributes(document.createElement("<input name='" + element.name + "'/>"), false);
 184.379 +                }
 184.380 +                catch(e) {} // For IE9 with doc mode "IE9 Standards" and browser mode "IE9 Compatibility View"
 184.381 +            }
 184.382 +        },
 184.383 +
 184.384 +        forceRefresh: function(node) {
 184.385 +            // Workaround for an IE9 rendering bug - https://github.com/SteveSanderson/knockout/issues/209
 184.386 +            if (ieVersion >= 9) {
 184.387 +                // For text nodes and comment nodes (most likely virtual elements), we will have to refresh the container
 184.388 +                var elem = node.nodeType == 1 ? node : node.parentNode;
 184.389 +                if (elem.style)
 184.390 +                    elem.style.zoom = elem.style.zoom;
 184.391 +            }
 184.392 +        },
 184.393 +
 184.394 +        ensureSelectElementIsRenderedCorrectly: function(selectElement) {
 184.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.
 184.396 +            // (See https://github.com/SteveSanderson/knockout/issues/312, http://stackoverflow.com/questions/5908494/select-only-shows-first-char-of-selected-option)
 184.397 +            if (ieVersion >= 9) {
 184.398 +                var originalWidth = selectElement.style.width;
 184.399 +                selectElement.style.width = 0;
 184.400 +                selectElement.style.width = originalWidth;
 184.401 +            }
 184.402 +        },
 184.403 +
 184.404 +        range: function (min, max) {
 184.405 +            min = ko.utils.unwrapObservable(min);
 184.406 +            max = ko.utils.unwrapObservable(max);
 184.407 +            var result = [];
 184.408 +            for (var i = min; i <= max; i++)
 184.409 +                result.push(i);
 184.410 +            return result;
 184.411 +        },
 184.412 +
 184.413 +        makeArray: function(arrayLikeObject) {
 184.414 +            var result = [];
 184.415 +            for (var i = 0, j = arrayLikeObject.length; i < j; i++) {
 184.416 +                result.push(arrayLikeObject[i]);
 184.417 +            };
 184.418 +            return result;
 184.419 +        },
 184.420 +
 184.421 +        isIe6 : isIe6,
 184.422 +        isIe7 : isIe7,
 184.423 +        ieVersion : ieVersion,
 184.424 +
 184.425 +        getFormFields: function(form, fieldName) {
 184.426 +            var fields = ko.utils.makeArray(form.getElementsByTagName("input")).concat(ko.utils.makeArray(form.getElementsByTagName("textarea")));
 184.427 +            var isMatchingField = (typeof fieldName == 'string')
 184.428 +                ? function(field) { return field.name === fieldName }
 184.429 +                : function(field) { return fieldName.test(field.name) }; // Treat fieldName as regex or object containing predicate
 184.430 +            var matches = [];
 184.431 +            for (var i = fields.length - 1; i >= 0; i--) {
 184.432 +                if (isMatchingField(fields[i]))
 184.433 +                    matches.push(fields[i]);
 184.434 +            };
 184.435 +            return matches;
 184.436 +        },
 184.437 +
 184.438 +        parseJson: function (jsonString) {
 184.439 +            if (typeof jsonString == "string") {
 184.440 +                jsonString = ko.utils.stringTrim(jsonString);
 184.441 +                if (jsonString) {
 184.442 +                    if (window.JSON && window.JSON.parse) // Use native parsing where available
 184.443 +                        return window.JSON.parse(jsonString);
 184.444 +                    return (new Function("return " + jsonString))(); // Fallback on less safe parsing for older browsers
 184.445 +                }
 184.446 +            }
 184.447 +            return null;
 184.448 +        },
 184.449 +
 184.450 +        stringifyJson: function (data, replacer, space) {   // replacer and space are optional
 184.451 +            if ((typeof JSON == "undefined") || (typeof JSON.stringify == "undefined"))
 184.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");
 184.453 +            return JSON.stringify(ko.utils.unwrapObservable(data), replacer, space);
 184.454 +        },
 184.455 +
 184.456 +        postJson: function (urlOrForm, data, options) {
 184.457 +            options = options || {};
 184.458 +            var params = options['params'] || {};
 184.459 +            var includeFields = options['includeFields'] || this.fieldsIncludedWithJsonPost;
 184.460 +            var url = urlOrForm;
 184.461 +
 184.462 +            // If we were given a form, use its 'action' URL and pick out any requested field values
 184.463 +            if((typeof urlOrForm == 'object') && (ko.utils.tagNameLower(urlOrForm) === "form")) {
 184.464 +                var originalForm = urlOrForm;
 184.465 +                url = originalForm.action;
 184.466 +                for (var i = includeFields.length - 1; i >= 0; i--) {
 184.467 +                    var fields = ko.utils.getFormFields(originalForm, includeFields[i]);
 184.468 +                    for (var j = fields.length - 1; j >= 0; j--)
 184.469 +                        params[fields[j].name] = fields[j].value;
 184.470 +                }
 184.471 +            }
 184.472 +
 184.473 +            data = ko.utils.unwrapObservable(data);
 184.474 +            var form = document.createElement("form");
 184.475 +            form.style.display = "none";
 184.476 +            form.action = url;
 184.477 +            form.method = "post";
 184.478 +            for (var key in data) {
 184.479 +                var input = document.createElement("input");
 184.480 +                input.name = key;
 184.481 +                input.value = ko.utils.stringifyJson(ko.utils.unwrapObservable(data[key]));
 184.482 +                form.appendChild(input);
 184.483 +            }
 184.484 +            for (var key in params) {
 184.485 +                var input = document.createElement("input");
 184.486 +                input.name = key;
 184.487 +                input.value = params[key];
 184.488 +                form.appendChild(input);
 184.489 +            }
 184.490 +            document.body.appendChild(form);
 184.491 +            options['submitter'] ? options['submitter'](form) : form.submit();
 184.492 +            setTimeout(function () { form.parentNode.removeChild(form); }, 0);
 184.493 +        }
 184.494 +    }
 184.495 +})();
 184.496 +
 184.497 +ko.exportSymbol('utils', ko.utils);
 184.498 +ko.exportSymbol('utils.arrayForEach', ko.utils.arrayForEach);
 184.499 +ko.exportSymbol('utils.arrayFirst', ko.utils.arrayFirst);
 184.500 +ko.exportSymbol('utils.arrayFilter', ko.utils.arrayFilter);
 184.501 +ko.exportSymbol('utils.arrayGetDistinctValues', ko.utils.arrayGetDistinctValues);
 184.502 +ko.exportSymbol('utils.arrayIndexOf', ko.utils.arrayIndexOf);
 184.503 +ko.exportSymbol('utils.arrayMap', ko.utils.arrayMap);
 184.504 +ko.exportSymbol('utils.arrayPushAll', ko.utils.arrayPushAll);
 184.505 +ko.exportSymbol('utils.arrayRemoveItem', ko.utils.arrayRemoveItem);
 184.506 +ko.exportSymbol('utils.extend', ko.utils.extend);
 184.507 +ko.exportSymbol('utils.fieldsIncludedWithJsonPost', ko.utils.fieldsIncludedWithJsonPost);
 184.508 +ko.exportSymbol('utils.getFormFields', ko.utils.getFormFields);
 184.509 +ko.exportSymbol('utils.peekObservable', ko.utils.peekObservable);
 184.510 +ko.exportSymbol('utils.postJson', ko.utils.postJson);
 184.511 +ko.exportSymbol('utils.parseJson', ko.utils.parseJson);
 184.512 +ko.exportSymbol('utils.registerEventHandler', ko.utils.registerEventHandler);
 184.513 +ko.exportSymbol('utils.stringifyJson', ko.utils.stringifyJson);
 184.514 +ko.exportSymbol('utils.range', ko.utils.range);
 184.515 +ko.exportSymbol('utils.toggleDomNodeCssClass', ko.utils.toggleDomNodeCssClass);
 184.516 +ko.exportSymbol('utils.triggerEvent', ko.utils.triggerEvent);
 184.517 +ko.exportSymbol('utils.unwrapObservable', ko.utils.unwrapObservable);
 184.518 +
 184.519 +if (!Function.prototype['bind']) {
 184.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)
 184.521 +    // In case the browser doesn't implement it natively, provide a JavaScript implementation. This implementation is based on the one in prototype.js
 184.522 +    Function.prototype['bind'] = function (object) {
 184.523 +        var originalFunction = this, args = Array.prototype.slice.call(arguments), object = args.shift();
 184.524 +        return function () {
 184.525 +            return originalFunction.apply(object, args.concat(Array.prototype.slice.call(arguments)));
 184.526 +        };
 184.527 +    };
 184.528 +}
 184.529 +
 184.530 +ko.utils.domData = new (function () {
 184.531 +    var uniqueId = 0;
 184.532 +    var dataStoreKeyExpandoPropertyName = "__ko__" + (new Date).getTime();
 184.533 +    var dataStore = {};
 184.534 +    return {
 184.535 +        get: function (node, key) {
 184.536 +            var allDataForNode = ko.utils.domData.getAll(node, false);
 184.537 +            return allDataForNode === undefined ? undefined : allDataForNode[key];
 184.538 +        },
 184.539 +        set: function (node, key, value) {
 184.540 +            if (value === undefined) {
 184.541 +                // Make sure we don't actually create a new domData key if we are actually deleting a value
 184.542 +                if (ko.utils.domData.getAll(node, false) === undefined)
 184.543 +                    return;
 184.544 +            }
 184.545 +            var allDataForNode = ko.utils.domData.getAll(node, true);
 184.546 +            allDataForNode[key] = value;
 184.547 +        },
 184.548 +        getAll: function (node, createIfNotFound) {
 184.549 +            var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
 184.550 +            var hasExistingDataStore = dataStoreKey && (dataStoreKey !== "null") && dataStore[dataStoreKey];
 184.551 +            if (!hasExistingDataStore) {
 184.552 +                if (!createIfNotFound)
 184.553 +                    return undefined;
 184.554 +                dataStoreKey = node[dataStoreKeyExpandoPropertyName] = "ko" + uniqueId++;
 184.555 +                dataStore[dataStoreKey] = {};
 184.556 +            }
 184.557 +            return dataStore[dataStoreKey];
 184.558 +        },
 184.559 +        clear: function (node) {
 184.560 +            var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
 184.561 +            if (dataStoreKey) {
 184.562 +                delete dataStore[dataStoreKey];
 184.563 +                node[dataStoreKeyExpandoPropertyName] = null;
 184.564 +                return true; // Exposing "did clean" flag purely so specs can infer whether things have been cleaned up as intended
 184.565 +            }
 184.566 +            return false;
 184.567 +        }
 184.568 +    }
 184.569 +})();
 184.570 +
 184.571 +ko.exportSymbol('utils.domData', ko.utils.domData);
 184.572 +ko.exportSymbol('utils.domData.clear', ko.utils.domData.clear); // Exporting only so specs can clear up after themselves fully
 184.573 +
 184.574 +ko.utils.domNodeDisposal = new (function () {
 184.575 +    var domDataKey = "__ko_domNodeDisposal__" + (new Date).getTime();
 184.576 +    var cleanableNodeTypes = { 1: true, 8: true, 9: true };       // Element, Comment, Document
 184.577 +    var cleanableNodeTypesWithDescendants = { 1: true, 9: true }; // Element, Document
 184.578 +
 184.579 +    function getDisposeCallbacksCollection(node, createIfNotFound) {
 184.580 +        var allDisposeCallbacks = ko.utils.domData.get(node, domDataKey);
 184.581 +        if ((allDisposeCallbacks === undefined) && createIfNotFound) {
 184.582 +            allDisposeCallbacks = [];
 184.583 +            ko.utils.domData.set(node, domDataKey, allDisposeCallbacks);
 184.584 +        }
 184.585 +        return allDisposeCallbacks;
 184.586 +    }
 184.587 +    function destroyCallbacksCollection(node) {
 184.588 +        ko.utils.domData.set(node, domDataKey, undefined);
 184.589 +    }
 184.590 +
 184.591 +    function cleanSingleNode(node) {
 184.592 +        // Run all the dispose callbacks
 184.593 +        var callbacks = getDisposeCallbacksCollection(node, false);
 184.594 +        if (callbacks) {
 184.595 +            callbacks = callbacks.slice(0); // Clone, as the array may be modified during iteration (typically, callbacks will remove themselves)
 184.596 +            for (var i = 0; i < callbacks.length; i++)
 184.597 +                callbacks[i](node);
 184.598 +        }
 184.599 +
 184.600 +        // Also erase the DOM data
 184.601 +        ko.utils.domData.clear(node);
 184.602 +
 184.603 +        // Special support for jQuery here because it's so commonly used.
 184.604 +        // Many jQuery plugins (including jquery.tmpl) store data using jQuery's equivalent of domData
 184.605 +        // so notify it to tear down any resources associated with the node & descendants here.
 184.606 +        if ((typeof jQuery == "function") && (typeof jQuery['cleanData'] == "function"))
 184.607 +            jQuery['cleanData']([node]);
 184.608 +
 184.609 +        // Also clear any immediate-child comment nodes, as these wouldn't have been found by
 184.610 +        // node.getElementsByTagName("*") in cleanNode() (comment nodes aren't elements)
 184.611 +        if (cleanableNodeTypesWithDescendants[node.nodeType])
 184.612 +            cleanImmediateCommentTypeChildren(node);
 184.613 +    }
 184.614 +
 184.615 +    function cleanImmediateCommentTypeChildren(nodeWithChildren) {
 184.616 +        var child, nextChild = nodeWithChildren.firstChild;
 184.617 +        while (child = nextChild) {
 184.618 +            nextChild = child.nextSibling;
 184.619 +            if (child.nodeType === 8)
 184.620 +                cleanSingleNode(child);
 184.621 +        }
 184.622 +    }
 184.623 +
 184.624 +    return {
 184.625 +        addDisposeCallback : function(node, callback) {
 184.626 +            if (typeof callback != "function")
 184.627 +                throw new Error("Callback must be a function");
 184.628 +            getDisposeCallbacksCollection(node, true).push(callback);
 184.629 +        },
 184.630 +
 184.631 +        removeDisposeCallback : function(node, callback) {
 184.632 +            var callbacksCollection = getDisposeCallbacksCollection(node, false);
 184.633 +            if (callbacksCollection) {
 184.634 +                ko.utils.arrayRemoveItem(callbacksCollection, callback);
 184.635 +                if (callbacksCollection.length == 0)
 184.636 +                    destroyCallbacksCollection(node);
 184.637 +            }
 184.638 +        },
 184.639 +
 184.640 +        cleanNode : function(node) {
 184.641 +            // First clean this node, where applicable
 184.642 +            if (cleanableNodeTypes[node.nodeType]) {
 184.643 +                cleanSingleNode(node);
 184.644 +
 184.645 +                // ... then its descendants, where applicable
 184.646 +                if (cleanableNodeTypesWithDescendants[node.nodeType]) {
 184.647 +                    // Clone the descendants list in case it changes during iteration
 184.648 +                    var descendants = [];
 184.649 +                    ko.utils.arrayPushAll(descendants, node.getElementsByTagName("*"));
 184.650 +                    for (var i = 0, j = descendants.length; i < j; i++)
 184.651 +                        cleanSingleNode(descendants[i]);
 184.652 +                }
 184.653 +            }
 184.654 +            return node;
 184.655 +        },
 184.656 +
 184.657 +        removeNode : function(node) {
 184.658 +            ko.cleanNode(node);
 184.659 +            if (node.parentNode)
 184.660 +                node.parentNode.removeChild(node);
 184.661 +        }
 184.662 +    }
 184.663 +})();
 184.664 +ko.cleanNode = ko.utils.domNodeDisposal.cleanNode; // Shorthand name for convenience
 184.665 +ko.removeNode = ko.utils.domNodeDisposal.removeNode; // Shorthand name for convenience
 184.666 +ko.exportSymbol('cleanNode', ko.cleanNode);
 184.667 +ko.exportSymbol('removeNode', ko.removeNode);
 184.668 +ko.exportSymbol('utils.domNodeDisposal', ko.utils.domNodeDisposal);
 184.669 +ko.exportSymbol('utils.domNodeDisposal.addDisposeCallback', ko.utils.domNodeDisposal.addDisposeCallback);
 184.670 +ko.exportSymbol('utils.domNodeDisposal.removeDisposeCallback', ko.utils.domNodeDisposal.removeDisposeCallback);
 184.671 +(function () {
 184.672 +    var leadingCommentRegex = /^(\s*)<!--(.*?)-->/;
 184.673 +
 184.674 +    function simpleHtmlParse(html) {
 184.675 +        // Based on jQuery's "clean" function, but only accounting for table-related elements.
 184.676 +        // If you have referenced jQuery, this won't be used anyway - KO will use jQuery's "clean" function directly
 184.677 +
 184.678 +        // Note that there's still an issue in IE < 9 whereby it will discard comment nodes that are the first child of
 184.679 +        // a descendant node. For example: "<div><!-- mycomment -->abc</div>" will get parsed as "<div>abc</div>"
 184.680 +        // This won't affect anyone who has referenced jQuery, and there's always the workaround of inserting a dummy node
 184.681 +        // (possibly a text node) in front of the comment. So, KO does not attempt to workaround this IE issue automatically at present.
 184.682 +
 184.683 +        // Trim whitespace, otherwise indexOf won't work as expected
 184.684 +        var tags = ko.utils.stringTrim(html).toLowerCase(), div = document.createElement("div");
 184.685 +
 184.686 +        // Finds the first match from the left column, and returns the corresponding "wrap" data from the right column
 184.687 +        var wrap = tags.match(/^<(thead|tbody|tfoot)/)              && [1, "<table>", "</table>"] ||
 184.688 +                   !tags.indexOf("<tr")                             && [2, "<table><tbody>", "</tbody></table>"] ||
 184.689 +                   (!tags.indexOf("<td") || !tags.indexOf("<th"))   && [3, "<table><tbody><tr>", "</tr></tbody></table>"] ||
 184.690 +                   /* anything else */                                 [0, "", ""];
 184.691 +
 184.692 +        // Go to html and back, then peel off extra wrappers
 184.693 +        // Note that we always prefix with some dummy text, because otherwise, IE<9 will strip out leading comment nodes in descendants. Total madness.
 184.694 +        var markup = "ignored<div>" + wrap[1] + html + wrap[2] + "</div>";
 184.695 +        if (typeof window['innerShiv'] == "function") {
 184.696 +            div.appendChild(window['innerShiv'](markup));
 184.697 +        } else {
 184.698 +            div.innerHTML = markup;
 184.699 +        }
 184.700 +
 184.701 +        // Move to the right depth
 184.702 +        while (wrap[0]--)
 184.703 +            div = div.lastChild;
 184.704 +
 184.705 +        return ko.utils.makeArray(div.lastChild.childNodes);
 184.706 +    }
 184.707 +
 184.708 +    function jQueryHtmlParse(html) {
 184.709 +        // jQuery's "parseHTML" function was introduced in jQuery 1.8.0 and is a documented public API.
 184.710 +        if (jQuery['parseHTML']) {
 184.711 +            return jQuery['parseHTML'](html);
 184.712 +        } else {
 184.713 +            // For jQuery < 1.8.0, we fall back on the undocumented internal "clean" function.
 184.714 +            var elems = jQuery['clean']([html]);
 184.715 +
 184.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.
 184.717 +            // Unfortunately, it never clears the dummy parent nodes from the document fragment, so it leaks memory over time.
 184.718 +            // Fix this by finding the top-most dummy parent element, and detaching it from its owner fragment.
 184.719 +            if (elems && elems[0]) {
 184.720 +                // Find the top-most parent element that's a direct child of a document fragment
 184.721 +                var elem = elems[0];
 184.722 +                while (elem.parentNode && elem.parentNode.nodeType !== 11 /* i.e., DocumentFragment */)
 184.723 +                    elem = elem.parentNode;
 184.724 +                // ... then detach it
 184.725 +                if (elem.parentNode)
 184.726 +                    elem.parentNode.removeChild(elem);
 184.727 +            }
 184.728 +
 184.729 +            return elems;
 184.730 +        }
 184.731 +    }
 184.732 +
 184.733 +    ko.utils.parseHtmlFragment = function(html) {
 184.734 +        return typeof jQuery != 'undefined' ? jQueryHtmlParse(html)   // As below, benefit from jQuery's optimisations where possible
 184.735 +                                            : simpleHtmlParse(html);  // ... otherwise, this simple logic will do in most common cases.
 184.736 +    };
 184.737 +
 184.738 +    ko.utils.setHtml = function(node, html) {
 184.739 +        ko.utils.emptyDomNode(node);
 184.740 +
 184.741 +        // There's no legitimate reason to display a stringified observable without unwrapping it, so we'll unwrap it
 184.742 +        html = ko.utils.unwrapObservable(html);
 184.743 +
 184.744 +        if ((html !== null) && (html !== undefined)) {
 184.745 +            if (typeof html != 'string')
 184.746 +                html = html.toString();
 184.747 +
 184.748 +            // jQuery contains a lot of sophisticated code to parse arbitrary HTML fragments,
 184.749 +            // for example <tr> elements which are not normally allowed to exist on their own.
 184.750 +            // If you've referenced jQuery we'll use that rather than duplicating its code.
 184.751 +            if (typeof jQuery != 'undefined') {
 184.752 +                jQuery(node)['html'](html);
 184.753 +            } else {
 184.754 +                // ... otherwise, use KO's own parsing logic.
 184.755 +                var parsedNodes = ko.utils.parseHtmlFragment(html);
 184.756 +                for (var i = 0; i < parsedNodes.length; i++)
 184.757 +                    node.appendChild(parsedNodes[i]);
 184.758 +            }
 184.759 +        }
 184.760 +    };
 184.761 +})();
 184.762 +
 184.763 +ko.exportSymbol('utils.parseHtmlFragment', ko.utils.parseHtmlFragment);
 184.764 +ko.exportSymbol('utils.setHtml', ko.utils.setHtml);
 184.765 +
 184.766 +ko.memoization = (function () {
 184.767 +    var memos = {};
 184.768 +
 184.769 +    function randomMax8HexChars() {
 184.770 +        return (((1 + Math.random()) * 0x100000000) | 0).toString(16).substring(1);
 184.771 +    }
 184.772 +    function generateRandomId() {
 184.773 +        return randomMax8HexChars() + randomMax8HexChars();
 184.774 +    }
 184.775 +    function findMemoNodes(rootNode, appendToArray) {
 184.776 +        if (!rootNode)
 184.777 +            return;
 184.778 +        if (rootNode.nodeType == 8) {
 184.779 +            var memoId = ko.memoization.parseMemoText(rootNode.nodeValue);
 184.780 +            if (memoId != null)
 184.781 +                appendToArray.push({ domNode: rootNode, memoId: memoId });
 184.782 +        } else if (rootNode.nodeType == 1) {
 184.783 +            for (var i = 0, childNodes = rootNode.childNodes, j = childNodes.length; i < j; i++)
 184.784 +                findMemoNodes(childNodes[i], appendToArray);
 184.785 +        }
 184.786 +    }
 184.787 +
 184.788 +    return {
 184.789 +        memoize: function (callback) {
 184.790 +            if (typeof callback != "function")
 184.791 +                throw new Error("You can only pass a function to ko.memoization.memoize()");
 184.792 +            var memoId = generateRandomId();
 184.793 +            memos[memoId] = callback;
 184.794 +            return "<!--[ko_memo:" + memoId + "]-->";
 184.795 +        },
 184.796 +
 184.797 +        unmemoize: function (memoId, callbackParams) {
 184.798 +            var callback = memos[memoId];
 184.799 +            if (callback === undefined)
 184.800 +                throw new Error("Couldn't find any memo with ID " + memoId + ". Perhaps it's already been unmemoized.");
 184.801 +            try {
 184.802 +                callback.apply(null, callbackParams || []);
 184.803 +                return true;
 184.804 +            }
 184.805 +            finally { delete memos[memoId]; }
 184.806 +        },
 184.807 +
 184.808 +        unmemoizeDomNodeAndDescendants: function (domNode, extraCallbackParamsArray) {
 184.809 +            var memos = [];
 184.810 +            findMemoNodes(domNode, memos);
 184.811 +            for (var i = 0, j = memos.length; i < j; i++) {
 184.812 +                var node = memos[i].domNode;
 184.813 +                var combinedParams = [node];
 184.814 +                if (extraCallbackParamsArray)
 184.815 +                    ko.utils.arrayPushAll(combinedParams, extraCallbackParamsArray);
 184.816 +                ko.memoization.unmemoize(memos[i].memoId, combinedParams);
 184.817 +                node.nodeValue = ""; // Neuter this node so we don't try to unmemoize it again
 184.818 +                if (node.parentNode)
 184.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)
 184.820 +            }
 184.821 +        },
 184.822 +
 184.823 +        parseMemoText: function (memoText) {
 184.824 +            var match = memoText.match(/^\[ko_memo\:(.*?)\]$/);
 184.825 +            return match ? match[1] : null;
 184.826 +        }
 184.827 +    };
 184.828 +})();
 184.829 +
 184.830 +ko.exportSymbol('memoization', ko.memoization);
 184.831 +ko.exportSymbol('memoization.memoize', ko.memoization.memoize);
 184.832 +ko.exportSymbol('memoization.unmemoize', ko.memoization.unmemoize);
 184.833 +ko.exportSymbol('memoization.parseMemoText', ko.memoization.parseMemoText);
 184.834 +ko.exportSymbol('memoization.unmemoizeDomNodeAndDescendants', ko.memoization.unmemoizeDomNodeAndDescendants);
 184.835 +ko.extenders = {
 184.836 +    'throttle': function(target, timeout) {
 184.837 +        // Throttling means two things:
 184.838 +
 184.839 +        // (1) For dependent observables, we throttle *evaluations* so that, no matter how fast its dependencies
 184.840 +        //     notify updates, the target doesn't re-evaluate (and hence doesn't notify) faster than a certain rate
 184.841 +        target['throttleEvaluation'] = timeout;
 184.842 +
 184.843 +        // (2) For writable targets (observables, or writable dependent observables), we throttle *writes*
 184.844 +        //     so the target cannot change value synchronously or faster than a certain rate
 184.845 +        var writeTimeoutInstance = null;
 184.846 +        return ko.dependentObservable({
 184.847 +            'read': target,
 184.848 +            'write': function(value) {
 184.849 +                clearTimeout(writeTimeoutInstance);
 184.850 +                writeTimeoutInstance = setTimeout(function() {
 184.851 +                    target(value);
 184.852 +                }, timeout);
 184.853 +            }
 184.854 +        });
 184.855 +    },
 184.856 +
 184.857 +    'notify': function(target, notifyWhen) {
 184.858 +        target["equalityComparer"] = notifyWhen == "always"
 184.859 +            ? function() { return false } // Treat all values as not equal
 184.860 +            : ko.observable["fn"]["equalityComparer"];
 184.861 +        return target;
 184.862 +    }
 184.863 +};
 184.864 +
 184.865 +function applyExtenders(requestedExtenders) {
 184.866 +    var target = this;
 184.867 +    if (requestedExtenders) {
 184.868 +        for (var key in requestedExtenders) {
 184.869 +            var extenderHandler = ko.extenders[key];
 184.870 +            if (typeof extenderHandler == 'function') {
 184.871 +                target = extenderHandler(target, requestedExtenders[key]);
 184.872 +            }
 184.873 +        }
 184.874 +    }
 184.875 +    return target;
 184.876 +}
 184.877 +
 184.878 +ko.exportSymbol('extenders', ko.extenders);
 184.879 +
 184.880 +ko.subscription = function (target, callback, disposeCallback) {
 184.881 +    this.target = target;
 184.882 +    this.callback = callback;
 184.883 +    this.disposeCallback = disposeCallback;
 184.884 +    ko.exportProperty(this, 'dispose', this.dispose);
 184.885 +};
 184.886 +ko.subscription.prototype.dispose = function () {
 184.887 +    this.isDisposed = true;
 184.888 +    this.disposeCallback();
 184.889 +};
 184.890 +
 184.891 +ko.subscribable = function () {
 184.892 +    this._subscriptions = {};
 184.893 +
 184.894 +    ko.utils.extend(this, ko.subscribable['fn']);
 184.895 +    ko.exportProperty(this, 'subscribe', this.subscribe);
 184.896 +    ko.exportProperty(this, 'extend', this.extend);
 184.897 +    ko.exportProperty(this, 'getSubscriptionsCount', this.getSubscriptionsCount);
 184.898 +}
 184.899 +
 184.900 +var defaultEvent = "change";
 184.901 +
 184.902 +ko.subscribable['fn'] = {
 184.903 +    subscribe: function (callback, callbackTarget, event) {
 184.904 +        event = event || defaultEvent;
 184.905 +        var boundCallback = callbackTarget ? callback.bind(callbackTarget) : callback;
 184.906 +
 184.907 +        var subscription = new ko.subscription(this, boundCallback, function () {
 184.908 +            ko.utils.arrayRemoveItem(this._subscriptions[event], subscription);
 184.909 +        }.bind(this));
 184.910 +
 184.911 +        if (!this._subscriptions[event])
 184.912 +            this._subscriptions[event] = [];
 184.913 +        this._subscriptions[event].push(subscription);
 184.914 +        return subscription;
 184.915 +    },
 184.916 +
 184.917 +    "notifySubscribers": function (valueToNotify, event) {
 184.918 +        event = event || defaultEvent;
 184.919 +        if (this._subscriptions[event]) {
 184.920 +            ko.dependencyDetection.ignore(function() {
 184.921 +                ko.utils.arrayForEach(this._subscriptions[event].slice(0), function (subscription) {
 184.922 +                    // In case a subscription was disposed during the arrayForEach cycle, check
 184.923 +                    // for isDisposed on each subscription before invoking its callback
 184.924 +                    if (subscription && (subscription.isDisposed !== true))
 184.925 +                        subscription.callback(valueToNotify);
 184.926 +                });
 184.927 +            }, this);
 184.928 +        }
 184.929 +    },
 184.930 +
 184.931 +    getSubscriptionsCount: function () {
 184.932 +        var total = 0;
 184.933 +        for (var eventName in this._subscriptions) {
 184.934 +            if (this._subscriptions.hasOwnProperty(eventName))
 184.935 +                total += this._subscriptions[eventName].length;
 184.936 +        }
 184.937 +        return total;
 184.938 +    },
 184.939 +
 184.940 +    extend: applyExtenders
 184.941 +};
 184.942 +
 184.943 +
 184.944 +ko.isSubscribable = function (instance) {
 184.945 +    return typeof instance.subscribe == "function" && typeof instance["notifySubscribers"] == "function";
 184.946 +};
 184.947 +
 184.948 +ko.exportSymbol('subscribable', ko.subscribable);
 184.949 +ko.exportSymbol('isSubscribable', ko.isSubscribable);
 184.950 +
 184.951 +ko.dependencyDetection = (function () {
 184.952 +    var _frames = [];
 184.953 +
 184.954 +    return {
 184.955 +        begin: function (callback) {
 184.956 +            _frames.push({ callback: callback, distinctDependencies:[] });
 184.957 +        },
 184.958 +
 184.959 +        end: function () {
 184.960 +            _frames.pop();
 184.961 +        },
 184.962 +
 184.963 +        registerDependency: function (subscribable) {
 184.964 +            if (!ko.isSubscribable(subscribable))
 184.965 +                throw new Error("Only subscribable things can act as dependencies");
 184.966 +            if (_frames.length > 0) {
 184.967 +                var topFrame = _frames[_frames.length - 1];
 184.968 +                if (!topFrame || ko.utils.arrayIndexOf(topFrame.distinctDependencies, subscribable) >= 0)
 184.969 +                    return;
 184.970 +                topFrame.distinctDependencies.push(subscribable);
 184.971 +                topFrame.callback(subscribable);
 184.972 +            }
 184.973 +        },
 184.974 +
 184.975 +        ignore: function(callback, callbackTarget, callbackArgs) {
 184.976 +            try {
 184.977 +                _frames.push(null);
 184.978 +                return callback.apply(callbackTarget, callbackArgs || []);
 184.979 +            } finally {
 184.980 +                _frames.pop();
 184.981 +            }
 184.982 +        }
 184.983 +    };
 184.984 +})();
 184.985 +var primitiveTypes = { 'undefined':true, 'boolean':true, 'number':true, 'string':true };
 184.986 +
 184.987 +ko.observable = function (initialValue) {
 184.988 +    var _latestValue = initialValue;
 184.989 +
 184.990 +    function observable() {
 184.991 +        if (arguments.length > 0) {
 184.992 +            // Write
 184.993 +
 184.994 +            // Ignore writes if the value hasn't changed
 184.995 +            if ((!observable['equalityComparer']) || !observable['equalityComparer'](_latestValue, arguments[0])) {
 184.996 +                observable.valueWillMutate();
 184.997 +                _latestValue = arguments[0];
 184.998 +                if (DEBUG) observable._latestValue = _latestValue;
 184.999 +                observable.valueHasMutated();
184.1000 +            }
184.1001 +            return this; // Permits chained assignments
184.1002 +        }
184.1003 +        else {
184.1004 +            // Read
184.1005 +            ko.dependencyDetection.registerDependency(observable); // The caller only needs to be notified of changes if they did a "read" operation
184.1006 +            return _latestValue;
184.1007 +        }
184.1008 +    }
184.1009 +    if (DEBUG) observable._latestValue = _latestValue;
184.1010 +    ko.subscribable.call(observable);
184.1011 +    observable.peek = function() { return _latestValue };
184.1012 +    observable.valueHasMutated = function () { observable["notifySubscribers"](_latestValue); }
184.1013 +    observable.valueWillMutate = function () { observable["notifySubscribers"](_latestValue, "beforeChange"); }
184.1014 +    ko.utils.extend(observable, ko.observable['fn']);
184.1015 +
184.1016 +    ko.exportProperty(observable, 'peek', observable.peek);
184.1017 +    ko.exportProperty(observable, "valueHasMutated", observable.valueHasMutated);
184.1018 +    ko.exportProperty(observable, "valueWillMutate", observable.valueWillMutate);
184.1019 +
184.1020 +    return observable;
184.1021 +}
184.1022 +
184.1023 +ko.observable['fn'] = {
184.1024 +    "equalityComparer": function valuesArePrimitiveAndEqual(a, b) {
184.1025 +        var oldValueIsPrimitive = (a === null) || (typeof(a) in primitiveTypes);
184.1026 +        return oldValueIsPrimitive ? (a === b) : false;
184.1027 +    }
184.1028 +};
184.1029 +
184.1030 +var protoProperty = ko.observable.protoProperty = "__ko_proto__";
184.1031 +ko.observable['fn'][protoProperty] = ko.observable;
184.1032 +
184.1033 +ko.hasPrototype = function(instance, prototype) {
184.1034 +    if ((instance === null) || (instance === undefined) || (instance[protoProperty] === undefined)) return false;
184.1035 +    if (instance[protoProperty] === prototype) return true;
184.1036 +    return ko.hasPrototype(instance[protoProperty], prototype); // Walk the prototype chain
184.1037 +};
184.1038 +
184.1039 +ko.isObservable = function (instance) {
184.1040 +    return ko.hasPrototype(instance, ko.observable);
184.1041 +}
184.1042 +ko.isWriteableObservable = function (instance) {
184.1043 +    // Observable
184.1044 +    if ((typeof instance == "function") && instance[protoProperty] === ko.observable)
184.1045 +        return true;
184.1046 +    // Writeable dependent observable
184.1047 +    if ((typeof instance == "function") && (instance[protoProperty] === ko.dependentObservable) && (instance.hasWriteFunction))
184.1048 +        return true;
184.1049 +    // Anything else
184.1050 +    return false;
184.1051 +}
184.1052 +
184.1053 +
184.1054 +ko.exportSymbol('observable', ko.observable);
184.1055 +ko.exportSymbol('isObservable', ko.isObservable);
184.1056 +ko.exportSymbol('isWriteableObservable', ko.isWriteableObservable);
184.1057 +ko.observableArray = function (initialValues) {
184.1058 +    if (arguments.length == 0) {
184.1059 +        // Zero-parameter constructor initializes to empty array
184.1060 +        initialValues = [];
184.1061 +    }
184.1062 +    if ((initialValues !== null) && (initialValues !== undefined) && !('length' in initialValues))
184.1063 +        throw new Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");
184.1064 +
184.1065 +    var result = ko.observable(initialValues);
184.1066 +    ko.utils.extend(result, ko.observableArray['fn']);
184.1067 +    return result;
184.1068 +}
184.1069 +
184.1070 +ko.observableArray['fn'] = {
184.1071 +    'remove': function (valueOrPredicate) {
184.1072 +        var underlyingArray = this.peek();
184.1073 +        var removedValues = [];
184.1074 +        var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
184.1075 +        for (var i = 0; i < underlyingArray.length; i++) {
184.1076 +            var value = underlyingArray[i];
184.1077 +            if (predicate(value)) {
184.1078 +                if (removedValues.length === 0) {
184.1079 +                    this.valueWillMutate();
184.1080 +                }
184.1081 +                removedValues.push(value);
184.1082 +                underlyingArray.splice(i, 1);
184.1083 +                i--;
184.1084 +            }
184.1085 +        }
184.1086 +        if (removedValues.length) {
184.1087 +            this.valueHasMutated();
184.1088 +        }
184.1089 +        return removedValues;
184.1090 +    },
184.1091 +
184.1092 +    'removeAll': function (arrayOfValues) {
184.1093 +        // If you passed zero args, we remove everything
184.1094 +        if (arrayOfValues === undefined) {
184.1095 +            var underlyingArray = this.peek();
184.1096 +            var allValues = underlyingArray.slice(0);
184.1097 +            this.valueWillMutate();
184.1098 +            underlyingArray.splice(0, underlyingArray.length);
184.1099 +            this.valueHasMutated();
184.1100 +            return allValues;
184.1101 +        }
184.1102 +        // If you passed an arg, we interpret it as an array of entries to remove
184.1103 +        if (!arrayOfValues)
184.1104 +            return [];
184.1105 +        return this['remove'](function (value) {
184.1106 +            return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
184.1107 +        });
184.1108 +    },
184.1109 +
184.1110 +    'destroy': function (valueOrPredicate) {
184.1111 +        var underlyingArray = this.peek();
184.1112 +        var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
184.1113 +        this.valueWillMutate();
184.1114 +        for (var i = underlyingArray.length - 1; i >= 0; i--) {
184.1115 +            var value = underlyingArray[i];
184.1116 +            if (predicate(value))
184.1117 +                underlyingArray[i]["_destroy"] = true;
184.1118 +        }
184.1119 +        this.valueHasMutated();
184.1120 +    },
184.1121 +
184.1122 +    'destroyAll': function (arrayOfValues) {
184.1123 +        // If you passed zero args, we destroy everything
184.1124 +        if (arrayOfValues === undefined)
184.1125 +            return this['destroy'](function() { return true });
184.1126 +
184.1127 +        // If you passed an arg, we interpret it as an array of entries to destroy
184.1128 +        if (!arrayOfValues)
184.1129 +            return [];
184.1130 +        return this['destroy'](function (value) {
184.1131 +            return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
184.1132 +        });
184.1133 +    },
184.1134 +
184.1135 +    'indexOf': function (item) {
184.1136 +        var underlyingArray = this();
184.1137 +        return ko.utils.arrayIndexOf(underlyingArray, item);
184.1138 +    },
184.1139 +
184.1140 +    'replace': function(oldItem, newItem) {
184.1141 +        var index = this['indexOf'](oldItem);
184.1142 +        if (index >= 0) {
184.1143 +            this.valueWillMutate();
184.1144 +            this.peek()[index] = newItem;
184.1145 +            this.valueHasMutated();
184.1146 +        }
184.1147 +    }
184.1148 +}
184.1149 +
184.1150 +// Populate ko.observableArray.fn with read/write functions from native arrays
184.1151 +// Important: Do not add any additional functions here that may reasonably be used to *read* data from the array
184.1152 +// because we'll eval them without causing subscriptions, so ko.computed output could end up getting stale
184.1153 +ko.utils.arrayForEach(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function (methodName) {
184.1154 +    ko.observableArray['fn'][methodName] = function () {
184.1155 +        // Use "peek" to avoid creating a subscription in any computed that we're executing in the context of
184.1156 +        // (for consistency with mutating regular observables)
184.1157 +        var underlyingArray = this.peek();
184.1158 +        this.valueWillMutate();
184.1159 +        var methodCallResult = underlyingArray[methodName].apply(underlyingArray, arguments);
184.1160 +        this.valueHasMutated();
184.1161 +        return methodCallResult;
184.1162 +    };
184.1163 +});
184.1164 +
184.1165 +// Populate ko.observableArray.fn with read-only functions from native arrays
184.1166 +ko.utils.arrayForEach(["slice"], function (methodName) {
184.1167 +    ko.observableArray['fn'][methodName] = function () {
184.1168 +        var underlyingArray = this();
184.1169 +        return underlyingArray[methodName].apply(underlyingArray, arguments);
184.1170 +    };
184.1171 +});
184.1172 +
184.1173 +ko.exportSymbol('observableArray', ko.observableArray);
184.1174 +ko.dependentObservable = function (evaluatorFunctionOrOptions, evaluatorFunctionTarget, options) {
184.1175 +    var _latestValue,
184.1176 +        _hasBeenEvaluated = false,
184.1177 +        _isBeingEvaluated = false,
184.1178 +        readFunction = evaluatorFunctionOrOptions;
184.1179 +
184.1180 +    if (readFunction && typeof readFunction == "object") {
184.1181 +        // Single-parameter syntax - everything is on this "options" param
184.1182 +        options = readFunction;
184.1183 +        readFunction = options["read"];
184.1184 +    } else {
184.1185 +        // Multi-parameter syntax - construct the options according to the params passed
184.1186 +        options = options || {};
184.1187 +        if (!readFunction)
184.1188 +            readFunction = options["read"];
184.1189 +    }
184.1190 +    if (typeof readFunction != "function")
184.1191 +        throw new Error("Pass a function that returns the value of the ko.computed");
184.1192 +
184.1193 +    function addSubscriptionToDependency(subscribable) {
184.1194 +        _subscriptionsToDependencies.push(subscribable.subscribe(evaluatePossiblyAsync));
184.1195 +    }
184.1196 +
184.1197 +    function disposeAllSubscriptionsToDependencies() {
184.1198 +        ko.utils.arrayForEach(_subscriptionsToDependencies, function (subscription) {
184.1199 +            subscription.dispose();
184.1200 +        });
184.1201 +        _subscriptionsToDependencies = [];
184.1202 +    }
184.1203 +
184.1204 +    function evaluatePossiblyAsync() {
184.1205 +        var throttleEvaluationTimeout = dependentObservable['throttleEvaluation'];
184.1206 +        if (throttleEvaluationTimeout && throttleEvaluationTimeout >= 0) {
184.1207 +            clearTimeout(evaluationTimeoutInstance);
184.1208 +            evaluationTimeoutInstance = setTimeout(evaluateImmediate, throttleEvaluationTimeout);
184.1209 +        } else
184.1210 +            evaluateImmediate();
184.1211 +    }
184.1212 +
184.1213 +    function evaluateImmediate() {
184.1214 +        if (_isBeingEvaluated) {
184.1215 +            // If the evaluation of a ko.computed causes side effects, it's possible that it will trigger its own re-evaluation.
184.1216 +            // This is not desirable (it's hard for a developer to realise a chain of dependencies might cause this, and they almost
184.1217 +            // certainly didn't intend infinite re-evaluations). So, for predictability, we simply prevent ko.computeds from causing
184.1218 +            // their own re-evaluation. Further discussion at https://github.com/SteveSanderson/knockout/pull/387
184.1219 +            return;
184.1220 +        }
184.1221 +
184.1222 +        // Don't dispose on first evaluation, because the "disposeWhen" callback might
184.1223 +        // e.g., dispose when the associated DOM element isn't in the doc, and it's not
184.1224 +        // going to be in the doc until *after* the first evaluation
184.1225 +        if (_hasBeenEvaluated && disposeWhen()) {
184.1226 +            dispose();
184.1227 +            return;
184.1228 +        }
184.1229 +
184.1230 +        _isBeingEvaluated = true;
184.1231 +        try {
184.1232 +            // Initially, we assume that none of the subscriptions are still being used (i.e., all are candidates for disposal).
184.1233 +            // Then, during evaluation, we cross off any that are in fact still being used.
184.1234 +            var disposalCandidates = ko.utils.arrayMap(_subscriptionsToDependencies, function(item) {return item.target;});
184.1235 +
184.1236 +            ko.dependencyDetection.begin(function(subscribable) {
184.1237 +                var inOld;
184.1238 +                if ((inOld = ko.utils.arrayIndexOf(disposalCandidates, subscribable)) >= 0)
184.1239 +                    disposalCandidates[inOld] = undefined; // Don't want to dispose this subscription, as it's still being used
184.1240 +                else
184.1241 +                    addSubscriptionToDependency(subscribable); // Brand new subscription - add it
184.1242 +            });
184.1243 +
184.1244 +            var newValue = readFunction.call(evaluatorFunctionTarget);
184.1245 +
184.1246 +            // For each subscription no longer being used, remove it from the active subscriptions list and dispose it
184.1247 +            for (var i = disposalCandidates.length - 1; i >= 0; i--) {
184.1248 +                if (disposalCandidates[i])
184.1249 +                    _subscriptionsToDependencies.splice(i, 1)[0].dispose();
184.1250 +            }
184.1251 +            _hasBeenEvaluated = true;
184.1252 +
184.1253 +            dependentObservable["notifySubscribers"](_latestValue, "beforeChange");
184.1254 +            _latestValue = newValue;
184.1255 +            if (DEBUG) dependentObservable._latestValue = _latestValue;
184.1256 +        } finally {
184.1257 +            ko.dependencyDetection.end();
184.1258 +        }
184.1259 +
184.1260 +        dependentObservable["notifySubscribers"](_latestValue);
184.1261 +        _isBeingEvaluated = false;
184.1262 +        if (!_subscriptionsToDependencies.length)
184.1263 +            dispose();
184.1264 +    }
184.1265 +
184.1266 +    function dependentObservable() {
184.1267 +        if (arguments.length > 0) {
184.1268 +            if (typeof writeFunction === "function") {
184.1269 +                // Writing a value
184.1270 +                writeFunction.apply(evaluatorFunctionTarget, arguments);
184.1271 +            } else {
184.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.");
184.1273 +            }
184.1274 +            return this; // Permits chained assignments
184.1275 +        } else {
184.1276 +            // Reading the value
184.1277 +            if (!_hasBeenEvaluated)
184.1278 +                evaluateImmediate();
184.1279 +            ko.dependencyDetection.registerDependency(dependentObservable);
184.1280 +            return _latestValue;
184.1281 +        }
184.1282 +    }
184.1283 +
184.1284 +    function peek() {
184.1285 +        if (!_hasBeenEvaluated)
184.1286 +            evaluateImmediate();
184.1287 +        return _latestValue;
184.1288 +    }
184.1289 +
184.1290 +    function isActive() {
184.1291 +        return !_hasBeenEvaluated || _subscriptionsToDependencies.length > 0;
184.1292 +    }
184.1293 +
184.1294 +    // By here, "options" is always non-null
184.1295 +    var writeFunction = options["write"],
184.1296 +        disposeWhenNodeIsRemoved = options["disposeWhenNodeIsRemoved"] || options.disposeWhenNodeIsRemoved || null,
184.1297 +        disposeWhen = options["disposeWhen"] || options.disposeWhen || function() { return false; },
184.1298 +        dispose = disposeAllSubscriptionsToDependencies,
184.1299 +        _subscriptionsToDependencies = [],
184.1300 +        evaluationTimeoutInstance = null;
184.1301 +
184.1302 +    if (!evaluatorFunctionTarget)
184.1303 +        evaluatorFunctionTarget = options["owner"];
184.1304 +
184.1305 +    dependentObservable.peek = peek;
184.1306 +    dependentObservable.getDependenciesCount = function () { return _subscriptionsToDependencies.length; };
184.1307 +    dependentObservable.hasWriteFunction = typeof options["write"] === "function";
184.1308 +    dependentObservable.dispose = function () { dispose(); };
184.1309 +    dependentObservable.isActive = isActive;
184.1310 +    dependentObservable.valueHasMutated = function() {
184.1311 +        _hasBeenEvaluated = false;
184.1312 +        evaluateImmediate();
184.1313 +    };
184.1314 +
184.1315 +    ko.subscribable.call(dependentObservable);
184.1316 +    ko.utils.extend(dependentObservable, ko.dependentObservable['fn']);
184.1317 +
184.1318 +    ko.exportProperty(dependentObservable, 'peek', dependentObservable.peek);
184.1319 +    ko.exportProperty(dependentObservable, 'dispose', dependentObservable.dispose);
184.1320 +    ko.exportProperty(dependentObservable, 'isActive', dependentObservable.isActive);
184.1321 +    ko.exportProperty(dependentObservable, 'getDependenciesCount', dependentObservable.getDependenciesCount);
184.1322 +
184.1323 +    // Evaluate, unless deferEvaluation is true
184.1324 +    if (options['deferEvaluation'] !== true)
184.1325 +        evaluateImmediate();
184.1326 +
184.1327 +    // Build "disposeWhenNodeIsRemoved" and "disposeWhenNodeIsRemovedCallback" option values.
184.1328 +    // But skip if isActive is false (there will never be any dependencies to dispose).
184.1329 +    // (Note: "disposeWhenNodeIsRemoved" option both proactively disposes as soon as the node is removed using ko.removeNode(),
184.1330 +    // plus adds a "disposeWhen" callback that, on each evaluation, disposes if the node was removed by some other means.)
184.1331 +    if (disposeWhenNodeIsRemoved && isActive()) {
184.1332 +        dispose = function() {
184.1333 +            ko.utils.domNodeDisposal.removeDisposeCallback(disposeWhenNodeIsRemoved, arguments.callee);
184.1334 +            disposeAllSubscriptionsToDependencies();
184.1335 +        };
184.1336 +        ko.utils.domNodeDisposal.addDisposeCallback(disposeWhenNodeIsRemoved, dispose);
184.1337 +        var existingDisposeWhenFunction = disposeWhen;
184.1338 +        disposeWhen = function () {
184.1339 +            return !ko.utils.domNodeIsAttachedToDocument(disposeWhenNodeIsRemoved) || existingDisposeWhenFunction();
184.1340 +        }
184.1341 +    }
184.1342 +
184.1343 +    return dependentObservable;
184.1344 +};
184.1345 +
184.1346 +ko.isComputed = function(instance) {
184.1347 +    return ko.hasPrototype(instance, ko.dependentObservable);
184.1348 +};
184.1349 +
184.1350 +var protoProp = ko.observable.protoProperty; // == "__ko_proto__"
184.1351 +ko.dependentObservable[protoProp] = ko.observable;
184.1352 +
184.1353 +ko.dependentObservable['fn'] = {};
184.1354 +ko.dependentObservable['fn'][protoProp] = ko.dependentObservable;
184.1355 +
184.1356 +ko.exportSymbol('dependentObservable', ko.dependentObservable);
184.1357 +ko.exportSymbol('computed', ko.dependentObservable); // Make "ko.computed" an alias for "ko.dependentObservable"
184.1358 +ko.exportSymbol('isComputed', ko.isComputed);
184.1359 +
184.1360 +(function() {
184.1361 +    var maxNestedObservableDepth = 10; // Escape the (unlikely) pathalogical case where an observable's current value is itself (or similar reference cycle)
184.1362 +
184.1363 +    ko.toJS = function(rootObject) {
184.1364 +        if (arguments.length == 0)
184.1365 +            throw new Error("When calling ko.toJS, pass the object you want to convert.");
184.1366 +
184.1367 +        // We just unwrap everything at every level in the object graph
184.1368 +        return mapJsObjectGraph(rootObject, function(valueToMap) {
184.1369 +            // Loop because an observable's value might in turn be another observable wrapper
184.1370 +            for (var i = 0; ko.isObservable(valueToMap) && (i < maxNestedObservableDepth); i++)
184.1371 +                valueToMap = valueToMap();
184.1372 +            return valueToMap;
184.1373 +        });
184.1374 +    };
184.1375 +
184.1376 +    ko.toJSON = function(rootObject, replacer, space) {     // replacer and space are optional
184.1377 +        var plainJavaScriptObject = ko.toJS(rootObject);
184.1378 +        return ko.utils.stringifyJson(plainJavaScriptObject, replacer, space);
184.1379 +    };
184.1380 +
184.1381 +    function mapJsObjectGraph(rootObject, mapInputCallback, visitedObjects) {
184.1382 +        visitedObjects = visitedObjects || new objectLookup();
184.1383 +
184.1384 +        rootObject = mapInputCallback(rootObject);
184.1385 +        var canHaveProperties = (typeof rootObject == "object") && (rootObject !== null) && (rootObject !== undefined) && (!(rootObject instanceof Date));
184.1386 +        if (!canHaveProperties)
184.1387 +            return rootObject;
184.1388 +
184.1389 +        var outputProperties = rootObject instanceof Array ? [] : {};
184.1390 +        visitedObjects.save(rootObject, outputProperties);
184.1391 +
184.1392 +        visitPropertiesOrArrayEntries(rootObject, function(indexer) {
184.1393 +            var propertyValue = mapInputCallback(rootObject[indexer]);
184.1394 +
184.1395 +            switch (typeof propertyValue) {
184.1396 +                case "boolean":
184.1397 +                case "number":
184.1398 +                case "string":
184.1399 +                case "function":
184.1400 +                    outputProperties[indexer] = propertyValue;
184.1401 +                    break;
184.1402 +                case "object":
184.1403 +                case "undefined":
184.1404 +                    var previouslyMappedValue = visitedObjects.get(propertyValue);
184.1405 +                    outputProperties[indexer] = (previouslyMappedValue !== undefined)
184.1406 +                        ? previouslyMappedValue
184.1407 +                        : mapJsObjectGraph(propertyValue, mapInputCallback, visitedObjects);
184.1408 +                    break;
184.1409 +            }
184.1410 +        });
184.1411 +
184.1412 +        return outputProperties;
184.1413 +    }
184.1414 +
184.1415 +    function visitPropertiesOrArrayEntries(rootObject, visitorCallback) {
184.1416 +        if (rootObject instanceof Array) {
184.1417 +            for (var i = 0; i < rootObject.length; i++)
184.1418 +                visitorCallback(i);
184.1419 +
184.1420 +            // For arrays, also respect toJSON property for custom mappings (fixes #278)
184.1421 +            if (typeof rootObject['toJSON'] == 'function')
184.1422 +                visitorCallback('toJSON');
184.1423 +        } else {
184.1424 +            for (var propertyName in rootObject)
184.1425 +                visitorCallback(propertyName);
184.1426 +        }
184.1427 +    };
184.1428 +
184.1429 +    function objectLookup() {
184.1430 +        var keys = [];
184.1431 +        var values = [];
184.1432 +        this.save = function(key, value) {
184.1433 +            var existingIndex = ko.utils.arrayIndexOf(keys, key);
184.1434 +            if (existingIndex >= 0)
184.1435 +                values[existingIndex] = value;
184.1436 +            else {
184.1437 +                keys.push(key);
184.1438 +                values.push(value);
184.1439 +            }
184.1440 +        };
184.1441 +        this.get = function(key) {
184.1442 +            var existingIndex = ko.utils.arrayIndexOf(keys, key);
184.1443 +            return (existingIndex >= 0) ? values[existingIndex] : undefined;
184.1444 +        };
184.1445 +    };
184.1446 +})();
184.1447 +
184.1448 +ko.exportSymbol('toJS', ko.toJS);
184.1449 +ko.exportSymbol('toJSON', ko.toJSON);
184.1450 +(function () {
184.1451 +    var hasDomDataExpandoProperty = '__ko__hasDomDataOptionValue__';
184.1452 +
184.1453 +    // Normally, SELECT elements and their OPTIONs can only take value of type 'string' (because the values
184.1454 +    // are stored on DOM attributes). ko.selectExtensions provides a way for SELECTs/OPTIONs to have values
184.1455 +    // that are arbitrary objects. This is very convenient when implementing things like cascading dropdowns.
184.1456 +    ko.selectExtensions = {
184.1457 +        readValue : function(element) {
184.1458 +            switch (ko.utils.tagNameLower(element)) {
184.1459 +                case 'option':
184.1460 +                    if (element[hasDomDataExpandoProperty] === true)
184.1461 +                        return ko.utils.domData.get(element, ko.bindingHandlers.options.optionValueDomDataKey);
184.1462 +                    return ko.utils.ieVersion <= 7
184.1463 +                        ? (element.getAttributeNode('value').specified ? element.value : element.text)
184.1464 +                        : element.value;
184.1465 +                case 'select':
184.1466 +                    return element.selectedIndex >= 0 ? ko.selectExtensions.readValue(element.options[element.selectedIndex]) : undefined;
184.1467 +                default:
184.1468 +                    return element.value;
184.1469 +            }
184.1470 +        },
184.1471 +
184.1472 +        writeValue: function(element, value) {
184.1473 +            switch (ko.utils.tagNameLower(element)) {
184.1474 +                case 'option':
184.1475 +                    switch(typeof value) {
184.1476 +                        case "string":
184.1477 +                            ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, undefined);
184.1478 +                            if (hasDomDataExpandoProperty in element) { // IE <= 8 throws errors if you delete non-existent properties from a DOM node
184.1479 +                                delete element[hasDomDataExpandoProperty];
184.1480 +                            }
184.1481 +                            element.value = value;
184.1482 +                            break;
184.1483 +                        default:
184.1484 +                            // Store arbitrary object using DomData
184.1485 +                            ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, value);
184.1486 +                            element[hasDomDataExpandoProperty] = true;
184.1487 +
184.1488 +                            // Special treatment of numbers is just for backward compatibility. KO 1.2.1 wrote numerical values to element.value.
184.1489 +                            element.value = typeof value === "number" ? value : "";
184.1490 +                            break;
184.1491 +                    }
184.1492 +                    break;
184.1493 +                case 'select':
184.1494 +                    for (var i = element.options.length - 1; i >= 0; i--) {
184.1495 +                        if (ko.selectExtensions.readValue(element.options[i]) == value) {
184.1496 +                            element.selectedIndex = i;
184.1497 +                            break;
184.1498 +                        }
184.1499 +                    }
184.1500 +                    break;
184.1501 +                default:
184.1502 +                    if ((value === null) || (value === undefined))
184.1503 +                        value = "";
184.1504 +                    element.value = value;
184.1505 +                    break;
184.1506 +            }
184.1507 +        }
184.1508 +    };
184.1509 +})();
184.1510 +
184.1511 +ko.exportSymbol('selectExtensions', ko.selectExtensions);
184.1512 +ko.exportSymbol('selectExtensions.readValue', ko.selectExtensions.readValue);
184.1513 +ko.exportSymbol('selectExtensions.writeValue', ko.selectExtensions.writeValue);
184.1514 +ko.expressionRewriting = (function () {
184.1515 +    var restoreCapturedTokensRegex = /\@ko_token_(\d+)\@/g;
184.1516 +    var javaScriptReservedWords = ["true", "false"];
184.1517 +
184.1518 +    // Matches something that can be assigned to--either an isolated identifier or something ending with a property accessor
184.1519 +    // This is designed to be simple and avoid false negatives, but could produce false positives (e.g., a+b.c).
184.1520 +    var javaScriptAssignmentTarget = /^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i;
184.1521 +
184.1522 +    function restoreTokens(string, tokens) {
184.1523 +        var prevValue = null;
184.1524 +        while (string != prevValue) { // Keep restoring tokens until it no longer makes a difference (they may be nested)
184.1525 +            prevValue = string;
184.1526 +            string = string.replace(restoreCapturedTokensRegex, function (match, tokenIndex) {
184.1527 +                return tokens[tokenIndex];
184.1528 +            });
184.1529 +        }
184.1530 +        return string;
184.1531 +    }
184.1532 +
184.1533 +    function getWriteableValue(expression) {
184.1534 +        if (ko.utils.arrayIndexOf(javaScriptReservedWords, ko.utils.stringTrim(expression).toLowerCase()) >= 0)
184.1535 +            return false;
184.1536 +        var match = expression.match(javaScriptAssignmentTarget);
184.1537 +        return match === null ? false : match[1] ? ('Object(' + match[1] + ')' + match[2]) : expression;
184.1538 +    }
184.1539 +
184.1540 +    function ensureQuoted(key) {
184.1541 +        var trimmedKey = ko.utils.stringTrim(key);
184.1542 +        switch (trimmedKey.length && trimmedKey.charAt(0)) {
184.1543 +            case "'":
184.1544 +            case '"':
184.1545 +                return key;
184.1546 +            default:
184.1547 +                return "'" + trimmedKey + "'";
184.1548 +        }
184.1549 +    }
184.1550 +
184.1551 +    return {
184.1552 +        bindingRewriteValidators: [],
184.1553 +
184.1554 +        parseObjectLiteral: function(objectLiteralString) {
184.1555 +            // A full tokeniser+lexer would add too much weight to this library, so here's a simple parser
184.1556 +            // that is sufficient just to split an object literal string into a set of top-level key-value pairs
184.1557 +
184.1558 +            var str = ko.utils.stringTrim(objectLiteralString);
184.1559 +            if (str.length < 3)
184.1560 +                return [];
184.1561 +            if (str.charAt(0) === "{")// Ignore any braces surrounding the whole object literal
184.1562 +                str = str.substring(1, str.length - 1);
184.1563 +
184.1564 +            // Pull out any string literals and regex literals
184.1565 +            var tokens = [];
184.1566 +            var tokenStart = null, tokenEndChar;
184.1567 +            for (var position = 0; position < str.length; position++) {
184.1568 +                var c = str.charAt(position);
184.1569 +                if (tokenStart === null) {
184.1570 +                    switch (c) {
184.1571 +                        case '"':
184.1572 +                        case "'":
184.1573 +                        case "/":
184.1574 +                            tokenStart = position;
184.1575 +                            tokenEndChar = c;
184.1576 +                            break;
184.1577 +                    }
184.1578 +                } else if ((c == tokenEndChar) && (str.charAt(position - 1) !== "\\")) {
184.1579 +                    var token = str.substring(tokenStart, position + 1);
184.1580 +                    tokens.push(token);
184.1581 +                    var replacement = "@ko_token_" + (tokens.length - 1) + "@";
184.1582 +                    str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
184.1583 +                    position -= (token.length - replacement.length);
184.1584 +                    tokenStart = null;
184.1585 +                }
184.1586 +            }
184.1587 +
184.1588 +            // Next pull out balanced paren, brace, and bracket blocks
184.1589 +            tokenStart = null;
184.1590 +            tokenEndChar = null;
184.1591 +            var tokenDepth = 0, tokenStartChar = null;
184.1592 +            for (var position = 0; position < str.length; position++) {
184.1593 +                var c = str.charAt(position);
184.1594 +                if (tokenStart === null) {
184.1595 +                    switch (c) {
184.1596 +                        case "{": tokenStart = position; tokenStartChar = c;
184.1597 +                                  tokenEndChar = "}";
184.1598 +                                  break;
184.1599 +                        case "(": tokenStart = position; tokenStartChar = c;
184.1600 +                                  tokenEndChar = ")";
184.1601 +                                  break;
184.1602 +                        case "[": tokenStart = position; tokenStartChar = c;
184.1603 +                                  tokenEndChar = "]";
184.1604 +                                  break;
184.1605 +                    }
184.1606 +                }
184.1607 +
184.1608 +                if (c === tokenStartChar)
184.1609 +                    tokenDepth++;
184.1610 +                else if (c === tokenEndChar) {
184.1611 +                    tokenDepth--;
184.1612 +                    if (tokenDepth === 0) {
184.1613 +                        var token = str.substring(tokenStart, position + 1);
184.1614 +                        tokens.push(token);
184.1615 +                        var replacement = "@ko_token_" + (tokens.length - 1) + "@";
184.1616 +                        str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
184.1617 +                        position -= (token.length - replacement.length);
184.1618 +                        tokenStart = null;
184.1619 +                    }
184.1620 +                }
184.1621 +            }
184.1622 +
184.1623 +            // Now we can safely split on commas to get the key/value pairs
184.1624 +            var result = [];
184.1625 +            var keyValuePairs = str.split(",");
184.1626 +            for (var i = 0, j = keyValuePairs.length; i < j; i++) {
184.1627 +                var pair = keyValuePairs[i];
184.1628 +                var colonPos = pair.indexOf(":");
184.1629 +                if ((colonPos > 0) && (colonPos < pair.length - 1)) {
184.1630 +                    var key = pair.substring(0, colonPos);
184.1631 +                    var value = pair.substring(colonPos + 1);
184.1632 +                    result.push({ 'key': restoreTokens(key, tokens), 'value': restoreTokens(value, tokens) });
184.1633 +                } else {
184.1634 +                    result.push({ 'unknown': restoreTokens(pair, tokens) });
184.1635 +                }
184.1636 +            }
184.1637 +            return result;
184.1638 +        },
184.1639 +
184.1640 +        preProcessBindings: function (objectLiteralStringOrKeyValueArray) {
184.1641 +            var keyValueArray = typeof objectLiteralStringOrKeyValueArray === "string"
184.1642 +                ? ko.expressionRewriting.parseObjectLiteral(objectLiteralStringOrKeyValueArray)
184.1643 +                : objectLiteralStringOrKeyValueArray;
184.1644 +            var resultStrings = [], propertyAccessorResultStrings = [];
184.1645 +
184.1646 +            var keyValueEntry;
184.1647 +            for (var i = 0; keyValueEntry = keyValueArray[i]; i++) {
184.1648 +                if (resultStrings.length > 0)
184.1649 +                    resultStrings.push(",");
184.1650 +
184.1651 +                if (keyValueEntry['key']) {
184.1652 +                    var quotedKey = ensureQuoted(keyValueEntry['key']), val = keyValueEntry['value'];
184.1653 +                    resultStrings.push(quotedKey);
184.1654 +                    resultStrings.push(":");
184.1655 +                    resultStrings.push(val);
184.1656 +
184.1657 +                    if (val = getWriteableValue(ko.utils.stringTrim(val))) {
184.1658 +                        if (propertyAccessorResultStrings.length > 0)
184.1659 +                            propertyAccessorResultStrings.push(", ");
184.1660 +                        propertyAccessorResultStrings.push(quotedKey + " : function(__ko_value) { " + val + " = __ko_value; }");
184.1661 +                    }
184.1662 +                } else if (keyValueEntry['unknown']) {
184.1663 +                    resultStrings.push(keyValueEntry['unknown']);
184.1664 +                }
184.1665 +            }
184.1666 +
184.1667 +            var combinedResult = resultStrings.join("");
184.1668 +            if (propertyAccessorResultStrings.length > 0) {
184.1669 +                var allPropertyAccessors = propertyAccessorResultStrings.join("");
184.1670 +                combinedResult = combinedResult + ", '_ko_property_writers' : { " + allPropertyAccessors + " } ";
184.1671 +            }
184.1672 +
184.1673 +            return combinedResult;
184.1674 +        },
184.1675 +
184.1676 +        keyValueArrayContainsKey: function(keyValueArray, key) {
184.1677 +            for (var i = 0; i < keyValueArray.length; i++)
184.1678 +                if (ko.utils.stringTrim(keyValueArray[i]['key']) == key)
184.1679 +                    return true;
184.1680 +            return false;
184.1681 +        },
184.1682 +
184.1683 +        // Internal, private KO utility for updating model properties from within bindings
184.1684 +        // property:            If the property being updated is (or might be) an observable, pass it here
184.1685 +        //                      If it turns out to be a writable observable, it will be written to directly
184.1686 +        // allBindingsAccessor: All bindings in the current execution context.
184.1687 +        //                      This will be searched for a '_ko_property_writers' property in case you're writing to a non-observable
184.1688 +        // key:                 The key identifying the property to be written. Example: for { hasFocus: myValue }, write to 'myValue' by specifying the key 'hasFocus'
184.1689 +        // value:               The value to be written
184.1690 +        // checkIfDifferent:    If true, and if the property being written is a writable observable, the value will only be written if
184.1691 +        //                      it is !== existing value on that writable observable
184.1692 +        writeValueToProperty: function(property, allBindingsAccessor, key, value, checkIfDifferent) {
184.1693 +            if (!property || !ko.isWriteableObservable(property)) {
184.1694 +                var propWriters = allBindingsAccessor()['_ko_property_writers'];
184.1695 +                if (propWriters && propWriters[key])
184.1696 +                    propWriters[key](value);
184.1697 +            } else if (!checkIfDifferent || property.peek() !== value) {
184.1698 +                property(value);
184.1699 +            }
184.1700 +        }
184.1701 +    };
184.1702 +})();
184.1703 +
184.1704 +ko.exportSymbol('expressionRewriting', ko.expressionRewriting);
184.1705 +ko.exportSymbol('expressionRewriting.bindingRewriteValidators', ko.expressionRewriting.bindingRewriteValidators);
184.1706 +ko.exportSymbol('expressionRewriting.parseObjectLiteral', ko.expressionRewriting.parseObjectLiteral);
184.1707 +ko.exportSymbol('expressionRewriting.preProcessBindings', ko.expressionRewriting.preProcessBindings);
184.1708 +
184.1709 +// For backward compatibility, define the following aliases. (Previously, these function names were misleading because
184.1710 +// they referred to JSON specifically, even though they actually work with arbitrary JavaScript object literal expressions.)
184.1711 +ko.exportSymbol('jsonExpressionRewriting', ko.expressionRewriting);
184.1712 +ko.exportSymbol('jsonExpressionRewriting.insertPropertyAccessorsIntoJson', ko.expressionRewriting.preProcessBindings);(function() {
184.1713 +    // "Virtual elements" is an abstraction on top of the usual DOM API which understands the notion that comment nodes
184.1714 +    // may be used to represent hierarchy (in addition to the DOM's natural hierarchy).
184.1715 +    // If you call the DOM-manipulating functions on ko.virtualElements, you will be able to read and write the state
184.1716 +    // of that virtual hierarchy
184.1717 +    //
184.1718 +    // The point of all this is to support containerless templates (e.g., <!-- ko foreach:someCollection -->blah<!-- /ko -->)
184.1719 +    // without having to scatter special cases all over the binding and templating code.
184.1720 +
184.1721 +    // IE 9 cannot reliably read the "nodeValue" property of a comment node (see https://github.com/SteveSanderson/knockout/issues/186)
184.1722 +    // but it does give them a nonstandard alternative property called "text" that it can read reliably. Other browsers don't have that property.
184.1723 +    // So, use node.text where available, and node.nodeValue elsewhere
184.1724 +    var commentNodesHaveTextProperty = document.createComment("test").text === "<!--test-->";
184.1725 +
184.1726 +    var startCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*-->$/ : /^\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*$/;
184.1727 +    var endCommentRegex =   commentNodesHaveTextProperty ? /^<!--\s*\/ko\s*-->$/ : /^\s*\/ko\s*$/;
184.1728 +    var htmlTagsWithOptionallyClosingChildren = { 'ul': true, 'ol': true };
184.1729 +
184.1730 +    function isStartComment(node) {
184.1731 +        return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(startCommentRegex);
184.1732 +    }
184.1733 +
184.1734 +    function isEndComment(node) {
184.1735 +        return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(endCommentRegex);
184.1736 +    }
184.1737 +
184.1738 +    function getVirtualChildren(startComment, allowUnbalanced) {
184.1739 +        var currentNode = startComment;
184.1740 +        var depth = 1;
184.1741 +        var children = [];
184.1742 +        while (currentNode = currentNode.nextSibling) {
184.1743 +            if (isEndComment(currentNode)) {
184.1744 +                depth--;
184.1745 +                if (depth === 0)
184.1746 +                    return children;
184.1747 +            }
184.1748 +
184.1749 +            children.push(currentNode);
184.1750 +
184.1751 +            if (isStartComment(currentNode))
184.1752 +                depth++;
184.1753 +        }
184.1754 +        if (!allowUnbalanced)
184.1755 +            throw new Error("Cannot find closing comment tag to match: " + startComment.nodeValue);
184.1756 +        return null;
184.1757 +    }
184.1758 +
184.1759 +    function getMatchingEndComment(startComment, allowUnbalanced) {
184.1760 +        var allVirtualChildren = getVirtualChildren(startComment, allowUnbalanced);
184.1761 +        if (allVirtualChildren) {
184.1762 +            if (allVirtualChildren.length > 0)
184.1763 +                return allVirtualChildren[allVirtualChildren.length - 1].nextSibling;
184.1764 +            return startComment.nextSibling;
184.1765 +        } else
184.1766 +            return null; // Must have no matching end comment, and allowUnbalanced is true
184.1767 +    }
184.1768 +
184.1769 +    function getUnbalancedChildTags(node) {
184.1770 +        // e.g., from <div>OK</div><!-- ko blah --><span>Another</span>, returns: <!-- ko blah --><span>Another</span>
184.1771 +        //       from <div>OK</div><!-- /ko --><!-- /ko -->,             returns: <!-- /ko --><!-- /ko -->
184.1772 +        var childNode = node.firstChild, captureRemaining = null;
184.1773 +        if (childNode) {
184.1774 +            do {
184.1775 +                if (captureRemaining)                   // We already hit an unbalanced node and are now just scooping up all subsequent nodes
184.1776 +                    captureRemaining.push(childNode);
184.1777 +                else if (isStartComment(childNode)) {
184.1778 +                    var matchingEndComment = getMatchingEndComment(childNode, /* allowUnbalanced: */ true);
184.1779 +                    if (matchingEndComment)             // It's a balanced tag, so skip immediately to the end of this virtual set
184.1780 +                        childNode = matchingEndComment;
184.1781 +                    else
184.1782 +                        captureRemaining = [childNode]; // It's unbalanced, so start capturing from this point
184.1783 +                } else if (isEndComment(childNode)) {
184.1784 +                    captureRemaining = [childNode];     // It's unbalanced (if it wasn't, we'd have skipped over it already), so start capturing
184.1785 +                }
184.1786 +            } while (childNode = childNode.nextSibling);
184.1787 +        }
184.1788 +        return captureRemaining;
184.1789 +    }
184.1790 +
184.1791 +    ko.virtualElements = {
184.1792 +        allowedBindings: {},
184.1793 +
184.1794 +        childNodes: function(node) {
184.1795 +            return isStartComment(node) ? getVirtualChildren(node) : node.childNodes;
184.1796 +        },
184.1797 +
184.1798 +        emptyNode: function(node) {
184.1799 +            if (!isStartComment(node))
184.1800 +                ko.utils.emptyDomNode(node);
184.1801 +            else {
184.1802 +                var virtualChildren = ko.virtualElements.childNodes(node);
184.1803 +                for (var i = 0, j = virtualChildren.length; i < j; i++)
184.1804 +                    ko.removeNode(virtualChildren[i]);
184.1805 +            }
184.1806 +        },
184.1807 +
184.1808 +        setDomNodeChildren: function(node, childNodes) {
184.1809 +            if (!isStartComment(node))
184.1810 +                ko.utils.setDomNodeChildren(node, childNodes);
184.1811 +            else {
184.1812 +                ko.virtualElements.emptyNode(node);
184.1813 +                var endCommentNode = node.nextSibling; // Must be the next sibling, as we just emptied the children
184.1814 +                for (var i = 0, j = childNodes.length; i < j; i++)
184.1815 +                    endCommentNode.parentNode.insertBefore(childNodes[i], endCommentNode);
184.1816 +            }
184.1817 +        },
184.1818 +
184.1819 +        prepend: function(containerNode, nodeToPrepend) {
184.1820 +            if (!isStartComment(containerNode)) {
184.1821 +                if (containerNode.firstChild)
184.1822 +                    containerNode.insertBefore(nodeToPrepend, containerNode.firstChild);
184.1823 +                else
184.1824 +                    containerNode.appendChild(nodeToPrepend);
184.1825 +            } else {
184.1826 +                // Start comments must always have a parent and at least one following sibling (the end comment)
184.1827 +                containerNode.parentNode.insertBefore(nodeToPrepend, containerNode.nextSibling);
184.1828 +            }
184.1829 +        },
184.1830 +
184.1831 +        insertAfter: function(containerNode, nodeToInsert, insertAfterNode) {
184.1832 +            if (!insertAfterNode) {
184.1833 +                ko.virtualElements.prepend(containerNode, nodeToInsert);
184.1834 +            } else if (!isStartComment(containerNode)) {
184.1835 +                // Insert after insertion point
184.1836 +                if (insertAfterNode.nextSibling)
184.1837 +                    containerNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
184.1838 +                else
184.1839 +                    containerNode.appendChild(nodeToInsert);
184.1840 +            } else {
184.1841 +                // Children of start comments must always have a parent and at least one following sibling (the end comment)
184.1842 +                containerNode.parentNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
184.1843 +            }
184.1844 +        },
184.1845 +
184.1846 +        firstChild: function(node) {
184.1847 +            if (!isStartComment(node))
184.1848 +                return node.firstChild;
184.1849 +            if (!node.nextSibling || isEndComment(node.nextSibling))
184.1850 +                return null;
184.1851 +            return node.nextSibling;
184.1852 +        },
184.1853 +
184.1854 +        nextSibling: function(node) {
184.1855 +            if (isStartComment(node))
184.1856 +                node = getMatchingEndComment(node);
184.1857 +            if (node.nextSibling && isEndComment(node.nextSibling))
184.1858 +                return null;
184.1859 +            return node.nextSibling;
184.1860 +        },
184.1861 +
184.1862 +        virtualNodeBindingValue: function(node) {
184.1863 +            var regexMatch = isStartComment(node);
184.1864 +            return regexMatch ? regexMatch[1] : null;
184.1865 +        },
184.1866 +
184.1867 +        normaliseVirtualElementDomStructure: function(elementVerified) {
184.1868 +            // Workaround for https://github.com/SteveSanderson/knockout/issues/155
184.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
184.1870 +            // that are direct descendants of <ul> into the preceding <li>)
184.1871 +            if (!htmlTagsWithOptionallyClosingChildren[ko.utils.tagNameLower(elementVerified)])
184.1872 +                return;
184.1873 +
184.1874 +            // Scan immediate children to see if they contain unbalanced comment tags. If they do, those comment tags
184.1875 +            // must be intended to appear *after* that child, so move them there.
184.1876 +            var childNode = elementVerified.firstChild;
184.1877 +            if (childNode) {
184.1878 +                do {
184.1879 +                    if (childNode.nodeType === 1) {
184.1880 +                        var unbalancedTags = getUnbalancedChildTags(childNode);
184.1881 +                        if (unbalancedTags) {
184.1882 +                            // Fix up the DOM by moving the unbalanced tags to where they most likely were intended to be placed - *after* the child
184.1883 +                            var nodeToInsertBefore = childNode.nextSibling;
184.1884 +                            for (var i = 0; i < unbalancedTags.length; i++) {
184.1885 +                                if (nodeToInsertBefore)
184.1886 +                                    elementVerified.insertBefore(unbalancedTags[i], nodeToInsertBefore);
184.1887 +                                else
184.1888 +                                    elementVerified.appendChild(unbalancedTags[i]);
184.1889 +                            }
184.1890 +                        }
184.1891 +                    }
184.1892 +                } while (childNode = childNode.nextSibling);
184.1893 +            }
184.1894 +        }
184.1895 +    };
184.1896 +})();
184.1897 +ko.exportSymbol('virtualElements', ko.virtualElements);
184.1898 +ko.exportSymbol('virtualElements.allowedBindings', ko.virtualElements.allowedBindings);
184.1899 +ko.exportSymbol('virtualElements.emptyNode', ko.virtualElements.emptyNode);
184.1900 +//ko.exportSymbol('virtualElements.firstChild', ko.virtualElements.firstChild);     // firstChild is not minified
184.1901 +ko.exportSymbol('virtualElements.insertAfter', ko.virtualElements.insertAfter);
184.1902 +//ko.exportSymbol('virtualElements.nextSibling', ko.virtualElements.nextSibling);   // nextSibling is not minified
184.1903 +ko.exportSymbol('virtualElements.prepend', ko.virtualElements.prepend);
184.1904 +ko.exportSymbol('virtualElements.setDomNodeChildren', ko.virtualElements.setDomNodeChildren);
184.1905 +(function() {
184.1906 +    var defaultBindingAttributeName = "data-bind";
184.1907 +
184.1908 +    ko.bindingProvider = function() {
184.1909 +        this.bindingCache = {};
184.1910 +    };
184.1911 +
184.1912 +    ko.utils.extend(ko.bindingProvider.prototype, {
184.1913 +        'nodeHasBindings': function(node) {
184.1914 +            switch (node.nodeType) {
184.1915 +                case 1: return node.getAttribute(defaultBindingAttributeName) != null;   // Element
184.1916 +                case 8: return ko.virtualElements.virtualNodeBindingValue(node) != null; // Comment node
184.1917 +                default: return false;
184.1918 +            }
184.1919 +        },
184.1920 +
184.1921 +        'getBindings': function(node, bindingContext) {
184.1922 +            var bindingsString = this['getBindingsString'](node, bindingContext);
184.1923 +            return bindingsString ? this['parseBindingsString'](bindingsString, bindingContext, node) : null;
184.1924 +        },
184.1925 +
184.1926 +        // The following function is only used internally by this default provider.
184.1927 +        // It's not part of the interface definition for a general binding provider.
184.1928 +        'getBindingsString': function(node, bindingContext) {
184.1929 +            switch (node.nodeType) {
184.1930 +                case 1: return node.getAttribute(defaultBindingAttributeName);   // Element
184.1931 +                case 8: return ko.virtualElements.virtualNodeBindingValue(node); // Comment node
184.1932 +                default: return null;
184.1933 +            }
184.1934 +        },
184.1935 +
184.1936 +        // The following function is only used internally by this default provider.
184.1937 +        // It's not part of the interface definition for a general binding provider.
184.1938 +        'parseBindingsString': function(bindingsString, bindingContext, node) {
184.1939 +            try {
184.1940 +                var bindingFunction = createBindingsStringEvaluatorViaCache(bindingsString, this.bindingCache);
184.1941 +                return bindingFunction(bindingContext, node);
184.1942 +            } catch (ex) {
184.1943 +                throw new Error("Unable to parse bindings.\nMessage: " + ex + ";\nBindings value: " + bindingsString);
184.1944 +            }
184.1945 +        }
184.1946 +    });
184.1947 +
184.1948 +    ko.bindingProvider['instance'] = new ko.bindingProvider();
184.1949 +
184.1950 +    function createBindingsStringEvaluatorViaCache(bindingsString, cache) {
184.1951 +        var cacheKey = bindingsString;
184.1952 +        return cache[cacheKey]
184.1953 +            || (cache[cacheKey] = createBindingsStringEvaluator(bindingsString));
184.1954 +    }
184.1955 +
184.1956 +    function createBindingsStringEvaluator(bindingsString) {
184.1957 +        // Build the source for a function that evaluates "expression"
184.1958 +        // For each scope variable, add an extra level of "with" nesting
184.1959 +        // Example result: with(sc1) { with(sc0) { return (expression) } }
184.1960 +        var rewrittenBindings = ko.expressionRewriting.preProcessBindings(bindingsString),
184.1961 +            functionBody = "with($context){with($data||{}){return{" + rewrittenBindings + "}}}";
184.1962 +        return new Function("$context", "$element", functionBody);
184.1963 +    }
184.1964 +})();
184.1965 +
184.1966 +ko.exportSymbol('bindingProvider', ko.bindingProvider);
184.1967 +(function () {
184.1968 +    ko.bindingHandlers = {};
184.1969 +
184.1970 +    ko.bindingContext = function(dataItem, parentBindingContext, dataItemAlias) {
184.1971 +        if (parentBindingContext) {
184.1972 +            ko.utils.extend(this, parentBindingContext); // Inherit $root and any custom properties
184.1973 +            this['$parentContext'] = parentBindingContext;
184.1974 +            this['$parent'] = parentBindingContext['$data'];
184.1975 +            this['$parents'] = (parentBindingContext['$parents'] || []).slice(0);
184.1976 +            this['$parents'].unshift(this['$parent']);
184.1977 +        } else {
184.1978 +            this['$parents'] = [];
184.1979 +            this['$root'] = dataItem;
184.1980 +            // Export 'ko' in the binding context so it will be available in bindings and templates
184.1981 +            // even if 'ko' isn't exported as a global, such as when using an AMD loader.
184.1982 +            // See https://github.com/SteveSanderson/knockout/issues/490
184.1983 +            this['ko'] = ko;
184.1984 +        }
184.1985 +        this['$data'] = dataItem;
184.1986 +        if (dataItemAlias)
184.1987 +            this[dataItemAlias] = dataItem;
184.1988 +    }
184.1989 +    ko.bindingContext.prototype['createChildContext'] = function (dataItem, dataItemAlias) {
184.1990 +        return new ko.bindingContext(dataItem, this, dataItemAlias);
184.1991 +    };
184.1992 +    ko.bindingContext.prototype['extend'] = function(properties) {
184.1993 +        var clone = ko.utils.extend(new ko.bindingContext(), this);
184.1994 +        return ko.utils.extend(clone, properties);
184.1995 +    };
184.1996 +
184.1997 +    function validateThatBindingIsAllowedForVirtualElements(bindingName) {
184.1998 +        var validator = ko.virtualElements.allowedBindings[bindingName];
184.1999 +        if (!validator)
184.2000 +            throw new Error("The binding '" + bindingName + "' cannot be used with virtual elements")
184.2001 +    }
184.2002 +
184.2003 +    function applyBindingsToDescendantsInternal (viewModel, elementOrVirtualElement, bindingContextsMayDifferFromDomParentElement) {
184.2004 +        var currentChild, nextInQueue = ko.virtualElements.firstChild(elementOrVirtualElement);
184.2005 +        while (currentChild = nextInQueue) {
184.2006 +            // Keep a record of the next child *before* applying bindings, in case the binding removes the current child from its position
184.2007 +            nextInQueue = ko.virtualElements.nextSibling(currentChild);
184.2008 +            applyBindingsToNodeAndDescendantsInternal(viewModel, currentChild, bindingContextsMayDifferFromDomParentElement);
184.2009 +        }
184.2010 +    }
184.2011 +
184.2012 +    function applyBindingsToNodeAndDescendantsInternal (viewModel, nodeVerified, bindingContextMayDifferFromDomParentElement) {
184.2013 +        var shouldBindDescendants = true;
184.2014 +
184.2015 +        // Perf optimisation: Apply bindings only if...
184.2016 +        // (1) We need to store the binding context on this node (because it may differ from the DOM parent node's binding context)
184.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
184.2018 +        // (2) It might have bindings (e.g., it has a data-bind attribute, or it's a marker for a containerless template)
184.2019 +        var isElement = (nodeVerified.nodeType === 1);
184.2020 +        if (isElement) // Workaround IE <= 8 HTML parsing weirdness
184.2021 +            ko.virtualElements.normaliseVirtualElementDomStructure(nodeVerified);
184.2022 +
184.2023 +        var shouldApplyBindings = (isElement && bindingContextMayDifferFromDomParentElement)             // Case (1)
184.2024 +                               || ko.bindingProvider['instance']['nodeHasBindings'](nodeVerified);       // Case (2)
184.2025 +        if (shouldApplyBindings)
184.2026 +            shouldBindDescendants = applyBindingsToNodeInternal(nodeVerified, null, viewModel, bindingContextMayDifferFromDomParentElement).shouldBindDescendants;
184.2027 +
184.2028 +        if (shouldBindDescendants) {
184.2029 +            // We're recursing automatically into (real or virtual) child nodes without changing binding contexts. So,
184.2030 +            //  * For children of a *real* element, the binding context is certainly the same as on their DOM .parentNode,
184.2031 +            //    hence bindingContextsMayDifferFromDomParentElement is false
184.2032 +            //  * For children of a *virtual* element, we can't be sure. Evaluating .parentNode on those children may
184.2033 +            //    skip over any number of intermediate virtual elements, any of which might define a custom binding context,
184.2034 +            //    hence bindingContextsMayDifferFromDomParentElement is true
184.2035 +            applyBindingsToDescendantsInternal(viewModel, nodeVerified, /* bindingContextsMayDifferFromDomParentElement: */ !isElement);
184.2036 +        }
184.2037 +    }
184.2038 +
184.2039 +    function applyBindingsToNodeInternal (node, bindings, viewModelOrBindingContext, bindingContextMayDifferFromDomParentElement) {
184.2040 +        // Need to be sure that inits are only run once, and updates never run until all the inits have been run
184.2041 +        var initPhase = 0; // 0 = before all inits, 1 = during inits, 2 = after all inits
184.2042 +
184.2043 +        // Each time the dependentObservable is evaluated (after data changes),
184.2044 +        // the binding attribute is reparsed so that it can pick out the correct
184.2045 +        // model properties in the context of the changed data.
184.2046 +        // DOM event callbacks need to be able to access this changed data,
184.2047 +        // so we need a single parsedBindings variable (shared by all callbacks
184.2048 +        // associated with this node's bindings) that all the closures can access.
184.2049 +        var parsedBindings;
184.2050 +        function makeValueAccessor(bindingKey) {
184.2051 +            return function () { return parsedBindings[bindingKey] }
184.2052 +        }
184.2053 +        function parsedBindingsAccessor() {
184.2054 +            return parsedBindings;
184.2055 +        }
184.2056 +
184.2057 +        var bindingHandlerThatControlsDescendantBindings;
184.2058 +        ko.dependentObservable(
184.2059 +            function () {
184.2060 +                // Ensure we have a nonnull binding context to work with
184.2061 +                var bindingContextInstance = viewModelOrBindingContext && (viewModelOrBindingContext instanceof ko.bindingContext)
184.2062 +                    ? viewModelOrBindingContext
184.2063 +                    : new ko.bindingContext(ko.utils.unwrapObservable(viewModelOrBindingContext));
184.2064 +                var viewModel = bindingContextInstance['$data'];
184.2065 +
184.2066 +                // Optimization: Don't store the binding context on this node if it's definitely the same as on node.parentNode, because
184.2067 +                // we can easily recover it just by scanning up the node's ancestors in the DOM
184.2068 +                // (note: here, parent node means "real DOM parent" not "virtual parent", as there's no O(1) way to find the virtual parent)
184.2069 +                if (bindingContextMayDifferFromDomParentElement)
184.2070 +                    ko.storedBindingContextForNode(node, bindingContextInstance);
184.2071 +
184.2072 +                // Use evaluatedBindings if given, otherwise fall back on asking the bindings provider to give us some bindings
184.2073 +                var evaluatedBindings = (typeof bindings == "function") ? bindings(bindingContextInstance, node) : bindings;
184.2074 +                parsedBindings = evaluatedBindings || ko.bindingProvider['instance']['getBindings'](node, bindingContextInstance);
184.2075 +
184.2076 +                if (parsedBindings) {
184.2077 +                    // First run all the inits, so bindings can register for notification on changes
184.2078 +                    if (initPhase === 0) {
184.2079 +                        initPhase = 1;
184.2080 +                        for (var bindingKey in parsedBindings) {
184.2081 +                            var binding = ko.bindingHandlers[bindingKey];
184.2082 +                            if (binding && node.nodeType === 8)
184.2083 +                                validateThatBindingIsAllowedForVirtualElements(bindingKey);
184.2084 +
184.2085 +                            if (binding && typeof binding["init"] == "function") {
184.2086 +                                var handlerInitFn = binding["init"];
184.2087 +                                var initResult = handlerInitFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
184.2088 +
184.2089 +                                // If this binding handler claims to control descendant bindings, make a note of this
184.2090 +                                if (initResult && initResult['controlsDescendantBindings']) {
184.2091 +                                    if (bindingHandlerThatControlsDescendantBindings !== undefined)
184.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.");
184.2093 +                                    bindingHandlerThatControlsDescendantBindings = bindingKey;
184.2094 +                                }
184.2095 +                            }
184.2096 +                        }
184.2097 +                        initPhase = 2;
184.2098 +                    }
184.2099 +
184.2100 +                    // ... then run all the updates, which might trigger changes even on the first evaluation
184.2101 +                    if (initPhase === 2) {
184.2102 +                        for (var bindingKey in parsedBindings) {
184.2103 +                            var binding = ko.bindingHandlers[bindingKey];
184.2104 +                            if (binding && typeof binding["update"] == "function") {
184.2105 +                                var handlerUpdateFn = binding["update"];
184.2106 +                                handlerUpdateFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
184.2107 +                            }
184.2108 +                        }
184.2109 +                    }
184.2110 +                }
184.2111 +            },
184.2112 +            null,
184.2113 +            { disposeWhenNodeIsRemoved : node }
184.2114 +        );
184.2115 +
184.2116 +        return {
184.2117 +            shouldBindDescendants: bindingHandlerThatControlsDescendantBindings === undefined
184.2118 +        };
184.2119 +    };
184.2120 +
184.2121 +    var storedBindingContextDomDataKey = "__ko_bindingContext__";
184.2122 +    ko.storedBindingContextForNode = function (node, bindingContext) {
184.2123 +        if (arguments.length == 2)
184.2124 +            ko.utils.domData.set(node, storedBindingContextDomDataKey, bindingContext);
184.2125 +        else
184.2126 +            return ko.utils.domData.get(node, storedBindingContextDomDataKey);
184.2127 +    }
184.2128 +
184.2129 +    ko.applyBindingsToNode = function (node, bindings, viewModel) {
184.2130 +        if (node.nodeType === 1) // If it's an element, workaround IE <= 8 HTML parsing weirdness
184.2131 +            ko.virtualElements.normaliseVirtualElementDomStructure(node);
184.2132 +        return applyBindingsToNodeInternal(node, bindings, viewModel, true);
184.2133 +    };
184.2134 +
184.2135 +    ko.applyBindingsToDescendants = function(viewModel, rootNode) {
184.2136 +        if (rootNode.nodeType === 1 || rootNode.nodeType === 8)
184.2137 +            applyBindingsToDescendantsInternal(viewModel, rootNode, true);
184.2138 +    };
184.2139 +
184.2140 +    ko.applyBindings = function (viewModel, rootNode) {
184.2141 +        if (rootNode && (rootNode.nodeType !== 1) && (rootNode.nodeType !== 8))
184.2142 +            throw new Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");
184.2143 +        rootNode = rootNode || window.document.body; // Make "rootNode" parameter optional
184.2144 +
184.2145 +        applyBindingsToNodeAndDescendantsInternal(viewModel, rootNode, true);
184.2146 +    };
184.2147 +
184.2148 +    // Retrieving binding context from arbitrary nodes
184.2149 +    ko.contextFor = function(node) {
184.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)
184.2151 +        switch (node.nodeType) {
184.2152 +            case 1:
184.2153 +            case 8:
184.2154 +                var context = ko.storedBindingContextForNode(node);
184.2155 +                if (context) return context;
184.2156 +                if (node.parentNode) return ko.contextFor(node.parentNode);
184.2157 +                break;
184.2158 +        }
184.2159 +        return undefined;
184.2160 +    };
184.2161 +    ko.dataFor = function(node) {
184.2162 +        var context = ko.contextFor(node);
184.2163 +        return context ? context['$data'] : undefined;
184.2164 +    };
184.2165 +
184.2166 +    ko.exportSymbol('bindingHandlers', ko.bindingHandlers);
184.2167 +    ko.exportSymbol('applyBindings', ko.applyBindings);
184.2168 +    ko.exportSymbol('applyBindingsToDescendants', ko.applyBindingsToDescendants);
184.2169 +    ko.exportSymbol('applyBindingsToNode', ko.applyBindingsToNode);
184.2170 +    ko.exportSymbol('contextFor', ko.contextFor);
184.2171 +    ko.exportSymbol('dataFor', ko.dataFor);
184.2172 +})();
184.2173 +var attrHtmlToJavascriptMap = { 'class': 'className', 'for': 'htmlFor' };
184.2174 +ko.bindingHandlers['attr'] = {
184.2175 +    'update': function(element, valueAccessor, allBindingsAccessor) {
184.2176 +        var value = ko.utils.unwrapObservable(valueAccessor()) || {};
184.2177 +        for (var attrName in value) {
184.2178 +            if (typeof attrName == "string") {
184.2179 +                var attrValue = ko.utils.unwrapObservable(value[attrName]);
184.2180 +
184.2181 +                // To cover cases like "attr: { checked:someProp }", we want to remove the attribute entirely
184.2182 +                // when someProp is a "no value"-like value (strictly null, false, or undefined)
184.2183 +                // (because the absence of the "checked" attr is how to mark an element as not checked, etc.)
184.2184 +                var toRemove = (attrValue === false) || (attrValue === null) || (attrValue === undefined);
184.2185 +                if (toRemove)
184.2186 +                    element.removeAttribute(attrName);
184.2187 +
184.2188 +                // In IE <= 7 and IE8 Quirks Mode, you have to use the Javascript property name instead of the
184.2189 +                // HTML attribute name for certain attributes. IE8 Standards Mode supports the correct behavior,
184.2190 +                // but instead of figuring out the mode, we'll just set the attribute through the Javascript
184.2191 +                // property for IE <= 8.
184.2192 +                if (ko.utils.ieVersion <= 8 && attrName in attrHtmlToJavascriptMap) {
184.2193 +                    attrName = attrHtmlToJavascriptMap[attrName];
184.2194 +                    if (toRemove)
184.2195 +                        element.removeAttribute(attrName);
184.2196 +                    else
184.2197 +                        element[attrName] = attrValue;
184.2198 +                } else if (!toRemove) {
184.2199 +                    try {
184.2200 +                        element.setAttribute(attrName, attrValue.toString());
184.2201 +                    } catch (err) {
184.2202 +                        // ignore for now
184.2203 +                        if (console) {
184.2204 +                            console.log("Can't set attribute " + attrName + " to " + attrValue + " error: " + err);
184.2205 +                        }
184.2206 +                    }
184.2207 +                }
184.2208 +
184.2209 +                // Treat "name" specially - although you can think of it as an attribute, it also needs
184.2210 +                // special handling on older versions of IE (https://github.com/SteveSanderson/knockout/pull/333)
184.2211 +                // Deliberately being case-sensitive here because XHTML would regard "Name" as a different thing
184.2212 +                // entirely, and there's no strong reason to allow for such casing in HTML.
184.2213 +                if (attrName === "name") {
184.2214 +                    ko.utils.setElementName(element, toRemove ? "" : attrValue.toString());
184.2215 +                }
184.2216 +            }
184.2217 +        }
184.2218 +    }
184.2219 +};
184.2220 +ko.bindingHandlers['checked'] = {
184.2221 +    'init': function (element, valueAccessor, allBindingsAccessor) {
184.2222 +        var updateHandler = function() {
184.2223 +            var valueToWrite;
184.2224 +            if (element.type == "checkbox") {
184.2225 +                valueToWrite = element.checked;
184.2226 +            } else if ((element.type == "radio") && (element.checked)) {
184.2227 +                valueToWrite = element.value;
184.2228 +            } else {
184.2229 +                return; // "checked" binding only responds to checkboxes and selected radio buttons
184.2230 +            }
184.2231 +
184.2232 +            var modelValue = valueAccessor(), unwrappedValue = ko.utils.unwrapObservable(modelValue);
184.2233 +            if ((element.type == "checkbox") && (unwrappedValue instanceof Array)) {
184.2234 +                // For checkboxes bound to an array, we add/remove the checkbox value to that array
184.2235 +                // This works for both observable and non-observable arrays
184.2236 +                var existingEntryIndex = ko.utils.arrayIndexOf(unwrappedValue, element.value);
184.2237 +                if (element.checked && (existingEntryIndex < 0))
184.2238 +                    modelValue.push(element.value);
184.2239 +                else if ((!element.checked) && (existingEntryIndex >= 0))
184.2240 +                    modelValue.splice(existingEntryIndex, 1);
184.2241 +            } else {
184.2242 +                ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'checked', valueToWrite, true);
184.2243 +            }
184.2244 +        };
184.2245 +        ko.utils.registerEventHandler(element, "click", updateHandler);
184.2246 +
184.2247 +        // IE 6 won't allow radio buttons to be selected unless they have a name
184.2248 +        if ((element.type == "radio") && !element.name)
184.2249 +            ko.bindingHandlers['uniqueName']['init'](element, function() { return true });
184.2250 +    },
184.2251 +    'update': function (element, valueAccessor) {
184.2252 +        var value = ko.utils.unwrapObservable(valueAccessor());
184.2253 +
184.2254 +        if (element.type == "checkbox") {
184.2255 +            if (value instanceof Array) {
184.2256 +                // When bound to an array, the checkbox being checked represents its value being present in that array
184.2257 +                element.checked = ko.utils.arrayIndexOf(value, element.value) >= 0;
184.2258 +            } else {
184.2259 +                // When bound to anything other value (not an array), the checkbox being checked represents the value being trueish
184.2260 +                element.checked = value;
184.2261 +            }
184.2262 +        } else if (element.type == "radio") {
184.2263 +            element.checked = (element.value == value);
184.2264 +        }
184.2265 +    }
184.2266 +};
184.2267 +var classesWrittenByBindingKey = '__ko__cssValue';
184.2268 +ko.bindingHandlers['css'] = {
184.2269 +    'update': function (element, valueAccessor) {
184.2270 +        var value = ko.utils.unwrapObservable(valueAccessor());
184.2271 +        if (typeof value == "object") {
184.2272 +            for (var className in value) {
184.2273 +                var shouldHaveClass = ko.utils.unwrapObservable(value[className]);
184.2274 +                ko.utils.toggleDomNodeCssClass(element, className, shouldHaveClass);
184.2275 +            }
184.2276 +        } else {
184.2277 +            value = String(value || ''); // Make sure we don't try to store or set a non-string value
184.2278 +            ko.utils.toggleDomNodeCssClass(element, element[classesWrittenByBindingKey], false);
184.2279 +            element[classesWrittenByBindingKey] = value;
184.2280 +            ko.utils.toggleDomNodeCssClass(element, value, true);
184.2281 +        }
184.2282 +    }
184.2283 +};
184.2284 +ko.bindingHandlers['enable'] = {
184.2285 +    'update': function (element, valueAccessor) {
184.2286 +        var value = ko.utils.unwrapObservable(valueAccessor());
184.2287 +        if (value && element.disabled)
184.2288 +            element.removeAttribute("disabled");
184.2289 +        else if ((!value) && (!element.disabled))
184.2290 +            element.disabled = true;
184.2291 +    }
184.2292 +};
184.2293 +
184.2294 +ko.bindingHandlers['disable'] = {
184.2295 +    'update': function (element, valueAccessor) {
184.2296 +        ko.bindingHandlers['enable']['update'](element, function() { return !ko.utils.unwrapObservable(valueAccessor()) });
184.2297 +    }
184.2298 +};
184.2299 +// For certain common events (currently just 'click'), allow a simplified data-binding syntax
184.2300 +// e.g. click:handler instead of the usual full-length event:{click:handler}
184.2301 +function makeEventHandlerShortcut(eventName) {
184.2302 +    ko.bindingHandlers[eventName] = {
184.2303 +        'init': function(element, valueAccessor, allBindingsAccessor, viewModel) {
184.2304 +            var newValueAccessor = function () {
184.2305 +                var result = {};
184.2306 +                result[eventName] = valueAccessor();
184.2307 +                return result;
184.2308 +            };
184.2309 +            return ko.bindingHandlers['event']['init'].call(this, element, newValueAccessor, allBindingsAccessor, viewModel);
184.2310 +        }
184.2311 +    }
184.2312 +}
184.2313 +
184.2314 +ko.bindingHandlers['event'] = {
184.2315 +    'init' : function (element, valueAccessor, allBindingsAccessor, viewModel) {
184.2316 +        var eventsToHandle = valueAccessor() || {};
184.2317 +        for(var eventNameOutsideClosure in eventsToHandle) {
184.2318 +            (function() {
184.2319 +                var eventName = eventNameOutsideClosure; // Separate variable to be captured by event handler closure
184.2320 +                if (typeof eventName == "string") {
184.2321 +                    ko.utils.registerEventHandler(element, eventName, function (event) {
184.2322 +                        var handlerReturnValue;
184.2323 +                        var handlerFunction = valueAccessor()[eventName];
184.2324 +                        if (!handlerFunction)
184.2325 +                            return;
184.2326 +                        var allBindings = allBindingsAccessor();
184.2327 +
184.2328 +                        try {
184.2329 +                            // Take all the event args, and prefix with the viewmodel
184.2330 +                            var argsForHandler = ko.utils.makeArray(arguments);
184.2331 +                            argsForHandler.unshift(viewModel);
184.2332 +                            handlerReturnValue = handlerFunction.apply(viewModel, argsForHandler);
184.2333 +                        } finally {
184.2334 +                            if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
184.2335 +                                if (event.preventDefault)
184.2336 +                                    event.preventDefault();
184.2337 +                                else
184.2338 +                                    event.returnValue = false;
184.2339 +                            }
184.2340 +                        }
184.2341 +
184.2342 +                        var bubble = allBindings[eventName + 'Bubble'] !== false;
184.2343 +                        if (!bubble) {
184.2344 +                            event.cancelBubble = true;
184.2345 +                            if (event.stopPropagation)
184.2346 +                                event.stopPropagation();
184.2347 +                        }
184.2348 +                    });
184.2349 +                }
184.2350 +            })();
184.2351 +        }
184.2352 +    }
184.2353 +};
184.2354 +// "foreach: someExpression" is equivalent to "template: { foreach: someExpression }"
184.2355 +// "foreach: { data: someExpression, afterAdd: myfn }" is equivalent to "template: { foreach: someExpression, afterAdd: myfn }"
184.2356 +ko.bindingHandlers['foreach'] = {
184.2357 +    makeTemplateValueAccessor: function(valueAccessor) {
184.2358 +        return function() {
184.2359 +            var modelValue = valueAccessor(),
184.2360 +                unwrappedValue = ko.utils.peekObservable(modelValue);    // Unwrap without setting a dependency here
184.2361 +
184.2362 +            // If unwrappedValue is the array, pass in the wrapped value on its own
184.2363 +            // The value will be unwrapped and tracked within the template binding
184.2364 +            // (See https://github.com/SteveSanderson/knockout/issues/523)
184.2365 +            if ((!unwrappedValue) || typeof unwrappedValue.length == "number")
184.2366 +                return { 'foreach': modelValue, 'templateEngine': ko.nativeTemplateEngine.instance };
184.2367 +
184.2368 +            // If unwrappedValue.data is the array, preserve all relevant options and unwrap again value so we get updates
184.2369 +            ko.utils.unwrapObservable(modelValue);
184.2370 +            return {
184.2371 +                'foreach': unwrappedValue['data'],
184.2372 +                'as': unwrappedValue['as'],
184.2373 +                'includeDestroyed': unwrappedValue['includeDestroyed'],
184.2374 +                'afterAdd': unwrappedValue['afterAdd'],
184.2375 +                'beforeRemove': unwrappedValue['beforeRemove'],
184.2376 +                'afterRender': unwrappedValue['afterRender'],
184.2377 +                'beforeMove': unwrappedValue['beforeMove'],
184.2378 +                'afterMove': unwrappedValue['afterMove'],
184.2379 +                'templateEngine': ko.nativeTemplateEngine.instance
184.2380 +            };
184.2381 +        };
184.2382 +    },
184.2383 +    'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
184.2384 +        return ko.bindingHandlers['template']['init'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor));
184.2385 +    },
184.2386 +    'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
184.2387 +        return ko.bindingHandlers['template']['update'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor), allBindingsAccessor, viewModel, bindingContext);
184.2388 +    }
184.2389 +};
184.2390 +ko.expressionRewriting.bindingRewriteValidators['foreach'] = false; // Can't rewrite control flow bindings
184.2391 +ko.virtualElements.allowedBindings['foreach'] = true;
184.2392 +var hasfocusUpdatingProperty = '__ko_hasfocusUpdating';
184.2393 +ko.bindingHandlers['hasfocus'] = {
184.2394 +    'init': function(element, valueAccessor, allBindingsAccessor) {
184.2395 +        var handleElementFocusChange = function(isFocused) {
184.2396 +            // Where possible, ignore which event was raised and determine focus state using activeElement,
184.2397 +            // as this avoids phantom focus/blur events raised when changing tabs in modern browsers.
184.2398 +            // However, not all KO-targeted browsers (Firefox 2) support activeElement. For those browsers,
184.2399 +            // prevent a loss of focus when changing tabs/windows by setting a flag that prevents hasfocus
184.2400 +            // from calling 'blur()' on the element when it loses focus.
184.2401 +            // Discussion at https://github.com/SteveSanderson/knockout/pull/352
184.2402 +            element[hasfocusUpdatingProperty] = true;
184.2403 +            var ownerDoc = element.ownerDocument;
184.2404 +            if ("activeElement" in ownerDoc) {
184.2405 +                isFocused = (ownerDoc.activeElement === element);
184.2406 +            }
184.2407 +            var modelValue = valueAccessor();
184.2408 +            ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'hasfocus', isFocused, true);
184.2409 +            element[hasfocusUpdatingProperty] = false;
184.2410 +        };
184.2411 +        var handleElementFocusIn = handleElementFocusChange.bind(null, true);
184.2412 +        var handleElementFocusOut = handleElementFocusChange.bind(null, false);
184.2413 +
184.2414 +        ko.utils.registerEventHandler(element, "focus", handleElementFocusIn);
184.2415 +        ko.utils.registerEventHandler(element, "focusin", handleElementFocusIn); // For IE
184.2416 +        ko.utils.registerEventHandler(element, "blur",  handleElementFocusOut);
184.2417 +        ko.utils.registerEventHandler(element, "focusout",  handleElementFocusOut); // For IE
184.2418 +    },
184.2419 +    'update': function(element, valueAccessor) {
184.2420 +        var value = ko.utils.unwrapObservable(valueAccessor());
184.2421 +        if (!element[hasfocusUpdatingProperty]) {
184.2422 +            value ? element.focus() : element.blur();
184.2423 +            ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, value ? "focusin" : "focusout"]); // For IE, which doesn't reliably fire "focus" or "blur" events synchronously
184.2424 +        }
184.2425 +    }
184.2426 +};
184.2427 +ko.bindingHandlers['html'] = {
184.2428 +    'init': function() {
184.2429 +        // Prevent binding on the dynamically-injected HTML (as developers are unlikely to expect that, and it has security implications)
184.2430 +        return { 'controlsDescendantBindings': true };
184.2431 +    },
184.2432 +    'update': function (element, valueAccessor) {
184.2433 +        // setHtml will unwrap the value if needed
184.2434 +        ko.utils.setHtml(element, valueAccessor());
184.2435 +    }
184.2436 +};
184.2437 +var withIfDomDataKey = '__ko_withIfBindingData';
184.2438 +// Makes a binding like with or if
184.2439 +function makeWithIfBinding(bindingKey, isWith, isNot, makeContextCallback) {
184.2440 +    ko.bindingHandlers[bindingKey] = {
184.2441 +        'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
184.2442 +            ko.utils.domData.set(element, withIfDomDataKey, {});
184.2443 +            return { 'controlsDescendantBindings': true };
184.2444 +        },
184.2445 +        'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
184.2446 +            var withIfData = ko.utils.domData.get(element, withIfDomDataKey),
184.2447 +                dataValue = ko.utils.unwrapObservable(valueAccessor()),
184.2448 +                shouldDisplay = !isNot !== !dataValue, // equivalent to isNot ? !dataValue : !!dataValue
184.2449 +                isFirstRender = !withIfData.savedNodes,
184.2450 +                needsRefresh = isFirstRender || isWith || (shouldDisplay !== withIfData.didDisplayOnLastUpdate);
184.2451 +
184.2452 +            if (needsRefresh) {
184.2453 +                if (isFirstRender) {
184.2454 +                    withIfData.savedNodes = ko.utils.cloneNodes(ko.virtualElements.childNodes(element), true /* shouldCleanNodes */);
184.2455 +                }
184.2456 +
184.2457 +                if (shouldDisplay) {
184.2458 +                    if (!isFirstRender) {
184.2459 +                        ko.virtualElements.setDomNodeChildren(element, ko.utils.cloneNodes(withIfData.savedNodes));
184.2460 +                    }
184.2461 +                    ko.applyBindingsToDescendants(makeContextCallback ? makeContextCallback(bindingContext, dataValue) : bindingContext, element);
184.2462 +                } else {
184.2463 +                    ko.virtualElements.emptyNode(element);
184.2464 +                }
184.2465 +
184.2466 +                withIfData.didDisplayOnLastUpdate = shouldDisplay;
184.2467 +            }
184.2468 +        }
184.2469 +    };
184.2470 +    ko.expressionRewriting.bindingRewriteValidators[bindingKey] = false; // Can't rewrite control flow bindings
184.2471 +    ko.virtualElements.allowedBindings[bindingKey] = true;
184.2472 +}
184.2473 +
184.2474 +// Construct the actual binding handlers
184.2475 +makeWithIfBinding('if');
184.2476 +makeWithIfBinding('ifnot', false /* isWith */, true /* isNot */);
184.2477 +makeWithIfBinding('with', true /* isWith */, false /* isNot */,
184.2478 +    function(bindingContext, dataValue) {
184.2479 +        return bindingContext['createChildContext'](dataValue);
184.2480 +    }
184.2481 +);
184.2482 +function ensureDropdownSelectionIsConsistentWithModelValue(element, modelValue, preferModelValue) {
184.2483 +    if (preferModelValue) {
184.2484 +        if (modelValue !== ko.selectExtensions.readValue(element))
184.2485 +            ko.selectExtensions.writeValue(element, modelValue);
184.2486 +    }
184.2487 +
184.2488 +    // No matter which direction we're syncing in, we want the end result to be equality between dropdown value and model value.
184.2489 +    // If they aren't equal, either we prefer the dropdown value, or the model value couldn't be represented, so either way,
184.2490 +    // change the model value to match the dropdown.
184.2491 +    if (modelValue !== ko.selectExtensions.readValue(element))
184.2492 +        ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, "change"]);
184.2493 +};
184.2494 +
184.2495 +ko.bindingHandlers['options'] = {
184.2496 +    'update': function (element, valueAccessor, allBindingsAccessor) {
184.2497 +        if (ko.utils.tagNameLower(element) !== "select")
184.2498 +            throw new Error("options binding applies only to SELECT elements");
184.2499 +
184.2500 +        var selectWasPreviouslyEmpty = element.length == 0;
184.2501 +        var previousSelectedValues = ko.utils.arrayMap(ko.utils.arrayFilter(element.childNodes, function (node) {
184.2502 +            return node.tagName && (ko.utils.tagNameLower(node) === "option") && node.selected;
184.2503 +        }), function (node) {
184.2504 +            return ko.selectExtensions.readValue(node) || node.innerText || node.textContent;
184.2505 +        });
184.2506 +        var previousScrollTop = element.scrollTop;
184.2507 +
184.2508 +        var value = ko.utils.unwrapObservable(valueAccessor());
184.2509 +        var selectedValue = element.value;
184.2510 +
184.2511 +        // Remove all existing <option>s.
184.2512 +        // Need to use .remove() rather than .removeChild() for <option>s otherwise IE behaves oddly (https://github.com/SteveSanderson/knockout/issues/134)
184.2513 +        while (element.length > 0) {
184.2514 +            ko.cleanNode(element.options[0]);
184.2515 +            element.remove(0);
184.2516 +        }
184.2517 +
184.2518 +        if (value) {
184.2519 +            var allBindings = allBindingsAccessor(),
184.2520 +                includeDestroyed = allBindings['optionsIncludeDestroyed'];
184.2521 +
184.2522 +            if (typeof value.length != "number")
184.2523 +                value = [value];
184.2524 +            if (allBindings['optionsCaption']) {
184.2525 +                var option = document.createElement("option");
184.2526 +                ko.utils.setHtml(option, allBindings['optionsCaption']);
184.2527 +                ko.selectExtensions.writeValue(option, undefined);
184.2528 +                element.appendChild(option);
184.2529 +            }
184.2530 +
184.2531 +            for (var i = 0, j = value.length; i < j; i++) {
184.2532 +                // Skip destroyed items
184.2533 +                var arrayEntry = value[i];
184.2534 +                if (arrayEntry && arrayEntry['_destroy'] && !includeDestroyed)
184.2535 +                    continue;
184.2536 +
184.2537 +                var option = document.createElement("option");
184.2538 +
184.2539 +                function applyToObject(object, predicate, defaultValue) {
184.2540 +                    var predicateType = typeof predicate;
184.2541 +                    if (predicateType == "function")    // Given a function; run it against the data value
184.2542 +                        return predicate(object);
184.2543 +                    else if (predicateType == "string") // Given a string; treat it as a property name on the data value
184.2544 +                        return object[predicate];
184.2545 +                    else                                // Given no optionsText arg; use the data value itself
184.2546 +                        return defaultValue;
184.2547 +                }
184.2548 +
184.2549 +                // Apply a value to the option element
184.2550 +                var optionValue = applyToObject(arrayEntry, allBindings['optionsValue'], arrayEntry);
184.2551 +                ko.selectExtensions.writeValue(option, ko.utils.unwrapObservable(optionValue));
184.2552 +
184.2553 +                // Apply some text to the option element
184.2554 +                var optionText = applyToObject(arrayEntry, allBindings['optionsText'], optionValue);
184.2555 +                ko.utils.setTextContent(option, optionText);
184.2556 +
184.2557 +                element.appendChild(option);
184.2558 +            }
184.2559 +
184.2560 +            // IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document.
184.2561 +            // That's why we first added them without selection. Now it's time to set the selection.
184.2562 +            var newOptions = element.getElementsByTagName("option");
184.2563 +            var countSelectionsRetained = 0;
184.2564 +            for (var i = 0, j = newOptions.length; i < j; i++) {
184.2565 +                if (ko.utils.arrayIndexOf(previousSelectedValues, ko.selectExtensions.readValue(newOptions[i])) >= 0) {
184.2566 +                    ko.utils.setOptionNodeSelectionState(newOptions[i], true);
184.2567 +                    countSelectionsRetained++;
184.2568 +                }
184.2569 +            }
184.2570 +
184.2571 +            element.scrollTop = previousScrollTop;
184.2572 +
184.2573 +            if (selectWasPreviouslyEmpty && ('value' in allBindings)) {
184.2574 +                // Ensure consistency between model value and selected option.
184.2575 +                // If the dropdown is being populated for the first time here (or was otherwise previously empty),
184.2576 +                // the dropdown selection state is meaningless, so we preserve the model value.
184.2577 +                ensureDropdownSelectionIsConsistentWithModelValue(element, ko.utils.peekObservable(allBindings['value']), /* preferModelValue */ true);
184.2578 +            }
184.2579 +
184.2580 +            // Workaround for IE9 bug
184.2581 +            ko.utils.ensureSelectElementIsRenderedCorrectly(element);
184.2582 +        }
184.2583 +    }
184.2584 +};
184.2585 +ko.bindingHandlers['options'].optionValueDomDataKey = '__ko.optionValueDomData__';
184.2586 +ko.bindingHandlers['selectedOptions'] = {
184.2587 +    'init': function (element, valueAccessor, allBindingsAccessor) {
184.2588 +        ko.utils.registerEventHandler(element, "change", function () {
184.2589 +            var value = valueAccessor(), valueToWrite = [];
184.2590 +            ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
184.2591 +                if (node.selected)
184.2592 +                    valueToWrite.push(ko.selectExtensions.readValue(node));
184.2593 +            });
184.2594 +            ko.expressionRewriting.writeValueToProperty(value, allBindingsAccessor, 'value', valueToWrite);
184.2595 +        });
184.2596 +    },
184.2597 +    'update': function (element, valueAccessor) {
184.2598 +        if (ko.utils.tagNameLower(element) != "select")
184.2599 +            throw new Error("values binding applies only to SELECT elements");
184.2600 +
184.2601 +        var newValue = ko.utils.unwrapObservable(valueAccessor());
184.2602 +        if (newValue && typeof newValue.length == "number") {
184.2603 +            ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
184.2604 +                var isSelected = ko.utils.arrayIndexOf(newValue, ko.selectExtensions.readValue(node)) >= 0;
184.2605 +                ko.utils.setOptionNodeSelectionState(node, isSelected);
184.2606 +            });
184.2607 +        }
184.2608 +    }
184.2609 +};
184.2610 +ko.bindingHandlers['style'] = {
184.2611 +    'update': function (element, valueAccessor) {
184.2612 +        var value = ko.utils.unwrapObservable(valueAccessor() || {});
184.2613 +        for (var styleName in value) {
184.2614 +            if (typeof styleName == "string") {
184.2615 +                var styleValue = ko.utils.unwrapObservable(value[styleName]);
184.2616 +                element.style[styleName] = styleValue || ""; // Empty string removes the value, whereas null/undefined have no effect
184.2617 +            }
184.2618 +        }
184.2619 +    }
184.2620 +};
184.2621 +ko.bindingHandlers['submit'] = {
184.2622 +    'init': function (element, valueAccessor, allBindingsAccessor, viewModel) {
184.2623 +        if (typeof valueAccessor() != "function")
184.2624 +            throw new Error("The value for a submit binding must be a function");
184.2625 +        ko.utils.registerEventHandler(element, "submit", function (event) {
184.2626 +            var handlerReturnValue;
184.2627 +            var value = valueAccessor();
184.2628 +            try { handlerReturnValue = value.call(viewModel, element); }
184.2629 +            finally {
184.2630 +                if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
184.2631 +                    if (event.preventDefault)
184.2632 +                        event.preventDefault();
184.2633 +                    else
184.2634 +                        event.returnValue = false;
184.2635 +                }
184.2636 +            }
184.2637 +        });
184.2638 +    }
184.2639 +};
184.2640 +ko.bindingHandlers['text'] = {
184.2641 +    'update': function (element, valueAccessor) {
184.2642 +        ko.utils.setTextContent(element, valueAccessor());
184.2643 +    }
184.2644 +};
184.2645 +ko.virtualElements.allowedBindings['text'] = true;
184.2646 +ko.bindingHandlers['uniqueName'] = {
184.2647 +    'init': function (element, valueAccessor) {
184.2648 +        if (valueAccessor()) {
184.2649 +            var name = "ko_unique_" + (++ko.bindingHandlers['uniqueName'].currentIndex);
184.2650 +            ko.utils.setElementName(element, name);
184.2651 +        }
184.2652 +    }
184.2653 +};
184.2654 +ko.bindingHandlers['uniqueName'].currentIndex = 0;
184.2655 +ko.bindingHandlers['value'] = {
184.2656 +    'init': function (element, valueAccessor, allBindingsAccessor) {
184.2657 +        // Always catch "change" event; possibly other events too if asked
184.2658 +        var eventsToCatch = ["change"];
184.2659 +        var requestedEventsToCatch = allBindingsAccessor()["valueUpdate"];
184.2660 +        var propertyChangedFired = false;
184.2661 +        if (requestedEventsToCatch) {
184.2662 +            if (typeof requestedEventsToCatch == "string") // Allow both individual event names, and arrays of event names
184.2663 +                requestedEventsToCatch = [requestedEventsToCatch];
184.2664 +            ko.utils.arrayPushAll(eventsToCatch, requestedEventsToCatch);
184.2665 +            eventsToCatch = ko.utils.arrayGetDistinctValues(eventsToCatch);
184.2666 +        }
184.2667 +
184.2668 +        var valueUpdateHandler = function() {
184.2669 +            propertyChangedFired = false;
184.2670 +            var modelValue = valueAccessor();
184.2671 +            var elementValue = ko.selectExtensions.readValue(element);
184.2672 +            ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'value', elementValue);
184.2673 +        }
184.2674 +
184.2675 +        // Workaround for https://github.com/SteveSanderson/knockout/issues/122
184.2676 +        // IE doesn't fire "change" events on textboxes if the user selects a value from its autocomplete list
184.2677 +        var ieAutoCompleteHackNeeded = ko.utils.ieVersion && element.tagName.toLowerCase() == "input" && element.type == "text"
184.2678 +                                       && element.autocomplete != "off" && (!element.form || element.form.autocomplete != "off");
184.2679 +        if (ieAutoCompleteHackNeeded && ko.utils.arrayIndexOf(eventsToCatch, "propertychange") == -1) {
184.2680 +            ko.utils.registerEventHandler(element, "propertychange", function () { propertyChangedFired = true });
184.2681 +            ko.utils.registerEventHandler(element, "blur", function() {
184.2682 +                if (propertyChangedFired) {
184.2683 +                    valueUpdateHandler();
184.2684 +                }
184.2685 +            });
184.2686 +        }
184.2687 +
184.2688 +        ko.utils.arrayForEach(eventsToCatch, function(eventName) {
184.2689 +            // The syntax "after<eventname>" means "run the handler asynchronously after the event"
184.2690 +            // This is useful, for example, to catch "keydown" events after the browser has updated the control
184.2691 +            // (otherwise, ko.selectExtensions.readValue(this) will receive the control's value *before* the key event)
184.2692 +            var handler = valueUpdateHandler;
184.2693 +            if (ko.utils.stringStartsWith(eventName, "after")) {
184.2694 +                handler = function() { setTimeout(valueUpdateHandler, 0) };
184.2695 +                eventName = eventName.substring("after".length);
184.2696 +            }
184.2697 +            ko.utils.registerEventHandler(element, eventName, handler);
184.2698 +        });
184.2699 +    },
184.2700 +    'update': function (element, valueAccessor) {
184.2701 +        var valueIsSelectOption = ko.utils.tagNameLower(element) === "select";
184.2702 +        var newValue = ko.utils.unwrapObservable(valueAccessor());
184.2703 +        var elementValue = ko.selectExtensions.readValue(element);
184.2704 +        var valueHasChanged = (newValue != elementValue);
184.2705 +
184.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).
184.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.
184.2708 +        if ((newValue === 0) && (elementValue !== 0) && (elementValue !== "0"))
184.2709 +            valueHasChanged = true;
184.2710 +
184.2711 +        if (valueHasChanged) {
184.2712 +            var applyValueAction = function () { ko.selectExtensions.writeValue(element, newValue); };
184.2713 +            applyValueAction();
184.2714 +
184.2715 +            // Workaround for IE6 bug: It won't reliably apply values to SELECT nodes during the same execution thread
184.2716 +            // right after you've changed the set of OPTION nodes on it. So for that node type, we'll schedule a second thread
184.2717 +            // to apply the value as well.
184.2718 +            var alsoApplyAsynchronously = valueIsSelectOption;
184.2719 +            if (alsoApplyAsynchronously)
184.2720 +                setTimeout(applyValueAction, 0);
184.2721 +        }
184.2722 +
184.2723 +        // If you try to set a model value that can't be represented in an already-populated dropdown, reject that change,
184.2724 +        // because you're not allowed to have a model value that disagrees with a visible UI selection.
184.2725 +        if (valueIsSelectOption && (element.length > 0))
184.2726 +            ensureDropdownSelectionIsConsistentWithModelValue(element, newValue, /* preferModelValue */ false);
184.2727 +    }
184.2728 +};
184.2729 +ko.bindingHandlers['visible'] = {
184.2730 +    'update': function (element, valueAccessor) {
184.2731 +        var value = ko.utils.unwrapObservable(valueAccessor());
184.2732 +        var isCurrentlyVisible = !(element.style.display == "none");
184.2733 +        if (value && !isCurrentlyVisible)
184.2734 +            element.style.display = "";
184.2735 +        else if ((!value) && isCurrentlyVisible)
184.2736 +            element.style.display = "none";
184.2737 +    }
184.2738 +};
184.2739 +// 'click' is just a shorthand for the usual full-length event:{click:handler}
184.2740 +makeEventHandlerShortcut('click');
184.2741 +// If you want to make a custom template engine,
184.2742 +//
184.2743 +// [1] Inherit from this class (like ko.nativeTemplateEngine does)
184.2744 +// [2] Override 'renderTemplateSource', supplying a function with this signature:
184.2745 +//
184.2746 +//        function (templateSource, bindingContext, options) {
184.2747 +//            // - templateSource.text() is the text of the template you should render
184.2748 +//            // - bindingContext.$data is the data you should pass into the template
184.2749 +//            //   - you might also want to make bindingContext.$parent, bindingContext.$parents,
184.2750 +//            //     and bindingContext.$root available in the template too
184.2751 +//            // - options gives you access to any other properties set on "data-bind: { template: options }"
184.2752 +//            //
184.2753 +//            // Return value: an array of DOM nodes
184.2754 +//        }
184.2755 +//
184.2756 +// [3] Override 'createJavaScriptEvaluatorBlock', supplying a function with this signature:
184.2757 +//
184.2758 +//        function (script) {
184.2759 +//            // Return value: Whatever syntax means "Evaluate the JavaScript statement 'script' and output the result"
184.2760 +//            //               For example, the jquery.tmpl template engine converts 'someScript' to '${ someScript }'
184.2761 +//        }
184.2762 +//
184.2763 +//     This is only necessary if you want to allow data-bind attributes to reference arbitrary template variables.
184.2764 +//     If you don't want to allow that, you can set the property 'allowTemplateRewriting' to false (like ko.nativeTemplateEngine does)
184.2765 +//     and then you don't need to override 'createJavaScriptEvaluatorBlock'.
184.2766 +
184.2767 +ko.templateEngine = function () { };
184.2768 +
184.2769 +ko.templateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
184.2770 +    throw new Error("Override renderTemplateSource");
184.2771 +};
184.2772 +
184.2773 +ko.templateEngine.prototype['createJavaScriptEvaluatorBlock'] = function (script) {
184.2774 +    throw new Error("Override createJavaScriptEvaluatorBlock");
184.2775 +};
184.2776 +
184.2777 +ko.templateEngine.prototype['makeTemplateSource'] = function(template, templateDocument) {
184.2778 +    // Named template
184.2779 +    if (typeof template == "string") {
184.2780 +        templateDocument = templateDocument || document;
184.2781 +        var elem = templateDocument.getElementById(template);
184.2782 +        if (!elem)
184.2783 +            throw new Error("Cannot find template with ID " + template);
184.2784 +        return new ko.templateSources.domElement(elem);
184.2785 +    } else if ((template.nodeType == 1) || (template.nodeType == 8)) {
184.2786 +        // Anonymous template
184.2787 +        return new ko.templateSources.anonymousTemplate(template);
184.2788 +    } else
184.2789 +        throw new Error("Unknown template type: " + template);
184.2790 +};
184.2791 +
184.2792 +ko.templateEngine.prototype['renderTemplate'] = function (template, bindingContext, options, templateDocument) {
184.2793 +    var templateSource = this['makeTemplateSource'](template, templateDocument);
184.2794 +    return this['renderTemplateSource'](templateSource, bindingContext, options);
184.2795 +};
184.2796 +
184.2797 +ko.templateEngine.prototype['isTemplateRewritten'] = function (template, templateDocument) {
184.2798 +    // Skip rewriting if requested
184.2799 +    if (this['allowTemplateRewriting'] === false)
184.2800 +        return true;
184.2801 +    return this['makeTemplateSource'](template, templateDocument)['data']("isRewritten");
184.2802 +};
184.2803 +
184.2804 +ko.templateEngine.prototype['rewriteTemplate'] = function (template, rewriterCallback, templateDocument) {
184.2805 +    var templateSource = this['makeTemplateSource'](template, templateDocument);
184.2806 +    var rewritten = rewriterCallback(templateSource['text']());
184.2807 +    templateSource['text'](rewritten);
184.2808 +    templateSource['data']("isRewritten", true);
184.2809 +};
184.2810 +
184.2811 +ko.exportSymbol('templateEngine', ko.templateEngine);
184.2812 +
184.2813 +ko.templateRewriting = (function () {
184.2814 +    var memoizeDataBindingAttributeSyntaxRegex = /(<[a-z]+\d*(\s+(?!data-bind=)[a-z0-9\-]+(=(\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind=(["'])([\s\S]*?)\5/gi;
184.2815 +    var memoizeVirtualContainerBindingSyntaxRegex = /<!--\s*ko\b\s*([\s\S]*?)\s*-->/g;
184.2816 +
184.2817 +    function validateDataBindValuesForRewriting(keyValueArray) {
184.2818 +        var allValidators = ko.expressionRewriting.bindingRewriteValidators;
184.2819 +        for (var i = 0; i < keyValueArray.length; i++) {
184.2820 +            var key = keyValueArray[i]['key'];
184.2821 +            if (allValidators.hasOwnProperty(key)) {
184.2822 +                var validator = allValidators[key];
184.2823 +
184.2824 +                if (typeof validator === "function") {
184.2825 +                    var possibleErrorMessage = validator(keyValueArray[i]['value']);
184.2826 +                    if (possibleErrorMessage)
184.2827 +                        throw new Error(possibleErrorMessage);
184.2828 +                } else if (!validator) {
184.2829 +                    throw new Error("This template engine does not support the '" + key + "' binding within its templates");
184.2830 +                }
184.2831 +            }
184.2832 +        }
184.2833 +    }
184.2834 +
184.2835 +    function constructMemoizedTagReplacement(dataBindAttributeValue, tagToRetain, templateEngine) {
184.2836 +        var dataBindKeyValueArray = ko.expressionRewriting.parseObjectLiteral(dataBindAttributeValue);
184.2837 +        validateDataBindValuesForRewriting(dataBindKeyValueArray);
184.2838 +        var rewrittenDataBindAttributeValue = ko.expressionRewriting.preProcessBindings(dataBindKeyValueArray);
184.2839 +
184.2840 +        // For no obvious reason, Opera fails to evaluate rewrittenDataBindAttributeValue unless it's wrapped in an additional
184.2841 +        // anonymous function, even though Opera's built-in debugger can evaluate it anyway. No other browser requires this
184.2842 +        // extra indirection.
184.2843 +        var applyBindingsToNextSiblingScript =
184.2844 +            "ko.__tr_ambtns(function($context,$element){return(function(){return{ " + rewrittenDataBindAttributeValue + " } })()})";
184.2845 +        return templateEngine['createJavaScriptEvaluatorBlock'](applyBindingsToNextSiblingScript) + tagToRetain;
184.2846 +    }
184.2847 +
184.2848 +    return {
184.2849 +        ensureTemplateIsRewritten: function (template, templateEngine, templateDocument) {
184.2850 +            if (!templateEngine['isTemplateRewritten'](template, templateDocument))
184.2851 +                templateEngine['rewriteTemplate'](template, function (htmlString) {
184.2852 +                    return ko.templateRewriting.memoizeBindingAttributeSyntax(htmlString, templateEngine);
184.2853 +                }, templateDocument);
184.2854 +        },
184.2855 +
184.2856 +        memoizeBindingAttributeSyntax: function (htmlString, templateEngine) {
184.2857 +            return htmlString.replace(memoizeDataBindingAttributeSyntaxRegex, function () {
184.2858 +                return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[6], /* tagToRetain: */ arguments[1], templateEngine);
184.2859 +            }).replace(memoizeVirtualContainerBindingSyntaxRegex, function() {
184.2860 +                return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[1], /* tagToRetain: */ "<!-- ko -->", templateEngine);
184.2861 +            });
184.2862 +        },
184.2863 +
184.2864 +        applyMemoizedBindingsToNextSibling: function (bindings) {
184.2865 +            return ko.memoization.memoize(function (domNode, bindingContext) {
184.2866 +                if (domNode.nextSibling)
184.2867 +                    ko.applyBindingsToNode(domNode.nextSibling, bindings, bindingContext);
184.2868 +            });
184.2869 +        }
184.2870 +    }
184.2871 +})();
184.2872 +
184.2873 +
184.2874 +// Exported only because it has to be referenced by string lookup from within rewritten template
184.2875 +ko.exportSymbol('__tr_ambtns', ko.templateRewriting.applyMemoizedBindingsToNextSibling);
184.2876 +(function() {
184.2877 +    // A template source represents a read/write way of accessing a template. This is to eliminate the need for template loading/saving
184.2878 +    // logic to be duplicated in every template engine (and means they can all work with anonymous templates, etc.)
184.2879 +    //
184.2880 +    // Two are provided by default:
184.2881 +    //  1. ko.templateSources.domElement       - reads/writes the text content of an arbitrary DOM element
184.2882 +    //  2. ko.templateSources.anonymousElement - uses ko.utils.domData to read/write text *associated* with the DOM element, but
184.2883 +    //                                           without reading/writing the actual element text content, since it will be overwritten
184.2884 +    //                                           with the rendered template output.
184.2885 +    // You can implement your own template source if you want to fetch/store templates somewhere other than in DOM elements.
184.2886 +    // Template sources need to have the following functions:
184.2887 +    //   text() 			- returns the template text from your storage location
184.2888 +    //   text(value)		- writes the supplied template text to your storage location
184.2889 +    //   data(key)			- reads values stored using data(key, value) - see below
184.2890 +    //   data(key, value)	- associates "value" with this template and the key "key". Is used to store information like "isRewritten".
184.2891 +    //
184.2892 +    // Optionally, template sources can also have the following functions:
184.2893 +    //   nodes()            - returns a DOM element containing the nodes of this template, where available
184.2894 +    //   nodes(value)       - writes the given DOM element to your storage location
184.2895 +    // If a DOM element is available for a given template source, template engines are encouraged to use it in preference over text()
184.2896 +    // for improved speed. However, all templateSources must supply text() even if they don't supply nodes().
184.2897 +    //
184.2898 +    // Once you've implemented a templateSource, make your template engine use it by subclassing whatever template engine you were
184.2899 +    // using and overriding "makeTemplateSource" to return an instance of your custom template source.
184.2900 +
184.2901 +    ko.templateSources = {};
184.2902 +
184.2903 +    // ---- ko.templateSources.domElement -----
184.2904 +
184.2905 +    ko.templateSources.domElement = function(element) {
184.2906 +        this.domElement = element;
184.2907 +    }
184.2908 +
184.2909 +    ko.templateSources.domElement.prototype['text'] = function(/* valueToWrite */) {
184.2910 +        var tagNameLower = ko.utils.tagNameLower(this.domElement),
184.2911 +            elemContentsProperty = tagNameLower === "script" ? "text"
184.2912 +                                 : tagNameLower === "textarea" ? "value"
184.2913 +                                 : "innerHTML";
184.2914 +
184.2915 +        if (arguments.length == 0) {
184.2916 +            return this.domElement[elemContentsProperty];
184.2917 +        } else {
184.2918 +            var valueToWrite = arguments[0];
184.2919 +            if (elemContentsProperty === "innerHTML")
184.2920 +                ko.utils.setHtml(this.domElement, valueToWrite);
184.2921 +            else
184.2922 +                this.domElement[elemContentsProperty] = valueToWrite;
184.2923 +        }
184.2924 +    };
184.2925 +
184.2926 +    ko.templateSources.domElement.prototype['data'] = function(key /*, valueToWrite */) {
184.2927 +        if (arguments.length === 1) {
184.2928 +            return ko.utils.domData.get(this.domElement, "templateSourceData_" + key);
184.2929 +        } else {
184.2930 +            ko.utils.domData.set(this.domElement, "templateSourceData_" + key, arguments[1]);
184.2931 +        }
184.2932 +    };
184.2933 +
184.2934 +    // ---- ko.templateSources.anonymousTemplate -----
184.2935 +    // Anonymous templates are normally saved/retrieved as DOM nodes through "nodes".
184.2936 +    // For compatibility, you can also read "text"; it will be serialized from the nodes on demand.
184.2937 +    // Writing to "text" is still supported, but then the template data will not be available as DOM nodes.
184.2938 +
184.2939 +    var anonymousTemplatesDomDataKey = "__ko_anon_template__";
184.2940 +    ko.templateSources.anonymousTemplate = function(element) {
184.2941 +        this.domElement = element;
184.2942 +    }
184.2943 +    ko.templateSources.anonymousTemplate.prototype = new ko.templateSources.domElement();
184.2944 +    ko.templateSources.anonymousTemplate.prototype['text'] = function(/* valueToWrite */) {
184.2945 +        if (arguments.length == 0) {
184.2946 +            var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
184.2947 +            if (templateData.textData === undefined && templateData.containerData)
184.2948 +                templateData.textData = templateData.containerData.innerHTML;
184.2949 +            return templateData.textData;
184.2950 +        } else {
184.2951 +            var valueToWrite = arguments[0];
184.2952 +            ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {textData: valueToWrite});
184.2953 +        }
184.2954 +    };
184.2955 +    ko.templateSources.domElement.prototype['nodes'] = function(/* valueToWrite */) {
184.2956 +        if (arguments.length == 0) {
184.2957 +            var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
184.2958 +            return templateData.containerData;
184.2959 +        } else {
184.2960 +            var valueToWrite = arguments[0];
184.2961 +            ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {containerData: valueToWrite});
184.2962 +        }
184.2963 +    };
184.2964 +
184.2965 +    ko.exportSymbol('templateSources', ko.templateSources);
184.2966 +    ko.exportSymbol('templateSources.domElement', ko.templateSources.domElement);
184.2967 +    ko.exportSymbol('templateSources.anonymousTemplate', ko.templateSources.anonymousTemplate);
184.2968 +})();
184.2969 +(function () {
184.2970 +    var _templateEngine;
184.2971 +    ko.setTemplateEngine = function (templateEngine) {
184.2972 +        if ((templateEngine != undefined) && !(templateEngine instanceof ko.templateEngine))
184.2973 +            throw new Error("templateEngine must inherit from ko.templateEngine");
184.2974 +        _templateEngine = templateEngine;
184.2975 +    }
184.2976 +
184.2977 +    function invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, action) {
184.2978 +        var node, nextInQueue = firstNode, firstOutOfRangeNode = ko.virtualElements.nextSibling(lastNode);
184.2979 +        while (nextInQueue && ((node = nextInQueue) !== firstOutOfRangeNode)) {
184.2980 +            nextInQueue = ko.virtualElements.nextSibling(node);
184.2981 +            if (node.nodeType === 1 || node.nodeType === 8)
184.2982 +                action(node);
184.2983 +        }
184.2984 +    }
184.2985 +
184.2986 +    function activateBindingsOnContinuousNodeArray(continuousNodeArray, bindingContext) {
184.2987 +        // To be used on any nodes that have been rendered by a template and have been inserted into some parent element
184.2988 +        // Walks through continuousNodeArray (which *must* be continuous, i.e., an uninterrupted sequence of sibling nodes, because
184.2989 +        // the algorithm for walking them relies on this), and for each top-level item in the virtual-element sense,
184.2990 +        // (1) Does a regular "applyBindings" to associate bindingContext with this node and to activate any non-memoized bindings
184.2991 +        // (2) Unmemoizes any memos in the DOM subtree (e.g., to activate bindings that had been memoized during template rewriting)
184.2992 +
184.2993 +        if (continuousNodeArray.length) {
184.2994 +            var firstNode = continuousNodeArray[0], lastNode = continuousNodeArray[continuousNodeArray.length - 1];
184.2995 +
184.2996 +            // Need to applyBindings *before* unmemoziation, because unmemoization might introduce extra nodes (that we don't want to re-bind)
184.2997 +            // whereas a regular applyBindings won't introduce new memoized nodes
184.2998 +            invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
184.2999 +                ko.applyBindings(bindingContext, node);
184.3000 +            });
184.3001 +            invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
184.3002 +                ko.memoization.unmemoizeDomNodeAndDescendants(node, [bindingContext]);
184.3003 +            });
184.3004 +        }
184.3005 +    }
184.3006 +
184.3007 +    function getFirstNodeFromPossibleArray(nodeOrNodeArray) {
184.3008 +        return nodeOrNodeArray.nodeType ? nodeOrNodeArray
184.3009 +                                        : nodeOrNodeArray.length > 0 ? nodeOrNodeArray[0]
184.3010 +                                        : null;
184.3011 +    }
184.3012 +
184.3013 +    function executeTemplate(targetNodeOrNodeArray, renderMode, template, bindingContext, options) {
184.3014 +        options = options || {};
184.3015 +        var firstTargetNode = targetNodeOrNodeArray && getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
184.3016 +        var templateDocument = firstTargetNode && firstTargetNode.ownerDocument;
184.3017 +        var templateEngineToUse = (options['templateEngine'] || _templateEngine);
184.3018 +        ko.templateRewriting.ensureTemplateIsRewritten(template, templateEngineToUse, templateDocument);
184.3019 +        var renderedNodesArray = templateEngineToUse['renderTemplate'](template, bindingContext, options, templateDocument);
184.3020 +
184.3021 +        // Loosely check result is an array of DOM nodes
184.3022 +        if ((typeof renderedNodesArray.length != "number") || (renderedNodesArray.length > 0 && typeof renderedNodesArray[0].nodeType != "number"))
184.3023 +            throw new Error("Template engine must return an array of DOM nodes");
184.3024 +
184.3025 +        var haveAddedNodesToParent = false;
184.3026 +        switch (renderMode) {
184.3027 +            case "replaceChildren":
184.3028 +                ko.virtualElements.setDomNodeChildren(targetNodeOrNodeArray, renderedNodesArray);
184.3029 +                haveAddedNodesToParent = true;
184.3030 +                break;
184.3031 +            case "replaceNode":
184.3032 +                ko.utils.replaceDomNodes(targetNodeOrNodeArray, renderedNodesArray);
184.3033 +                haveAddedNodesToParent = true;
184.3034 +                break;
184.3035 +            case "ignoreTargetNode": break;
184.3036 +            default:
184.3037 +                throw new Error("Unknown renderMode: " + renderMode);
184.3038 +        }
184.3039 +
184.3040 +        if (haveAddedNodesToParent) {
184.3041 +            activateBindingsOnContinuousNodeArray(renderedNodesArray, bindingContext);
184.3042 +            if (options['afterRender'])
184.3043 +                ko.dependencyDetection.ignore(options['afterRender'], null, [renderedNodesArray, bindingContext['$data']]);
184.3044 +        }
184.3045 +
184.3046 +        return renderedNodesArray;
184.3047 +    }
184.3048 +
184.3049 +    ko.renderTemplate = function (template, dataOrBindingContext, options, targetNodeOrNodeArray, renderMode) {
184.3050 +        options = options || {};
184.3051 +        if ((options['templateEngine'] || _templateEngine) == undefined)
184.3052 +            throw new Error("Set a template engine before calling renderTemplate");
184.3053 +        renderMode = renderMode || "replaceChildren";
184.3054 +
184.3055 +        if (targetNodeOrNodeArray) {
184.3056 +            var firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
184.3057 +
184.3058 +            var whenToDispose = function () { return (!firstTargetNode) || !ko.utils.domNodeIsAttachedToDocument(firstTargetNode); }; // Passive disposal (on next evaluation)
184.3059 +            var activelyDisposeWhenNodeIsRemoved = (firstTargetNode && renderMode == "replaceNode") ? firstTargetNode.parentNode : firstTargetNode;
184.3060 +
184.3061 +            return ko.dependentObservable( // So the DOM is automatically updated when any dependency changes
184.3062 +                function () {
184.3063 +                    // Ensure we've got a proper binding context to work with
184.3064 +                    var bindingContext = (dataOrBindingContext && (dataOrBindingContext instanceof ko.bindingContext))
184.3065 +                        ? dataOrBindingContext
184.3066 +                        : new ko.bindingContext(ko.utils.unwrapObservable(dataOrBindingContext));
184.3067 +
184.3068 +                    // Support selecting template as a function of the data being rendered
184.3069 +                    var templateName = typeof(template) == 'function' ? template(bindingContext['$data'], bindingContext) : template;
184.3070 +
184.3071 +                    var renderedNodesArray = executeTemplate(targetNodeOrNodeArray, renderMode, templateName, bindingContext, options);
184.3072 +                    if (renderMode == "replaceNode") {
184.3073 +                        targetNodeOrNodeArray = renderedNodesArray;
184.3074 +                        firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
184.3075 +                    }
184.3076 +                },
184.3077 +                null,
184.3078 +                { disposeWhen: whenToDispose, disposeWhenNodeIsRemoved: activelyDisposeWhenNodeIsRemoved }
184.3079 +            );
184.3080 +        } else {
184.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
184.3082 +            return ko.memoization.memoize(function (domNode) {
184.3083 +                ko.renderTemplate(template, dataOrBindingContext, options, domNode, "replaceNode");
184.3084 +            });
184.3085 +        }
184.3086 +    };
184.3087 +
184.3088 +    ko.renderTemplateForEach = function (template, arrayOrObservableArray, options, targetNode, parentBindingContext) {
184.3089 +        // Since setDomNodeChildrenFromArrayMapping always calls executeTemplateForArrayItem and then
184.3090 +        // activateBindingsCallback for added items, we can store the binding context in the former to use in the latter.
184.3091 +        var arrayItemContext;
184.3092 +
184.3093 +        // This will be called by setDomNodeChildrenFromArrayMapping to get the nodes to add to targetNode
184.3094 +        var executeTemplateForArrayItem = function (arrayValue, index) {
184.3095 +            // Support selecting template as a function of the data being rendered
184.3096 +            arrayItemContext = parentBindingContext['createChildContext'](ko.utils.unwrapObservable(arrayValue), options['as']);
184.3097 +            arrayItemContext['$index'] = index;
184.3098 +            var templateName = typeof(template) == 'function' ? template(arrayValue, arrayItemContext) : template;
184.3099 +            return executeTemplate(null, "ignoreTargetNode", templateName, arrayItemContext, options);
184.3100 +        }
184.3101 +
184.3102 +        // This will be called whenever setDomNodeChildrenFromArrayMapping has added nodes to targetNode
184.3103 +        var activateBindingsCallback = function(arrayValue, addedNodesArray, index) {
184.3104 +            activateBindingsOnContinuousNodeArray(addedNodesArray, arrayItemContext);
184.3105 +            if (options['afterRender'])
184.3106 +                options['afterRender'](addedNodesArray, arrayValue);
184.3107 +        };
184.3108 +
184.3109 +        return ko.dependentObservable(function () {
184.3110 +            var unwrappedArray = ko.utils.unwrapObservable(arrayOrObservableArray) || [];
184.3111 +            if (typeof unwrappedArray.length == "undefined") // Coerce single value into array
184.3112 +                unwrappedArray = [unwrappedArray];
184.3113 +
184.3114 +            // Filter out any entries marked as destroyed
184.3115 +            var filteredArray = ko.utils.arrayFilter(unwrappedArray, function(item) {
184.3116 +                return options['includeDestroyed'] || item === undefined || item === null || !ko.utils.unwrapObservable(item['_destroy']);
184.3117 +            });
184.3118 +
184.3119 +            // Call setDomNodeChildrenFromArrayMapping, ignoring any observables unwrapped within (most likely from a callback function).
184.3120 +            // If the array items are observables, though, they will be unwrapped in executeTemplateForArrayItem and managed within setDomNodeChildrenFromArrayMapping.
184.3121 +            ko.dependencyDetection.ignore(ko.utils.setDomNodeChildrenFromArrayMapping, null, [targetNode, filteredArray, executeTemplateForArrayItem, options, activateBindingsCallback]);
184.3122 +
184.3123 +        }, null, { disposeWhenNodeIsRemoved: targetNode });
184.3124 +    };
184.3125 +
184.3126 +    var templateComputedDomDataKey = '__ko__templateComputedDomDataKey__';
184.3127 +    function disposeOldComputedAndStoreNewOne(element, newComputed) {
184.3128 +        var oldComputed = ko.utils.domData.get(element, templateComputedDomDataKey);
184.3129 +        if (oldComputed && (typeof(oldComputed.dispose) == 'function'))
184.3130 +            oldComputed.dispose();
184.3131 +        ko.utils.domData.set(element, templateComputedDomDataKey, (newComputed && newComputed.isActive()) ? newComputed : undefined);
184.3132 +    }
184.3133 +
184.3134 +    ko.bindingHandlers['template'] = {
184.3135 +        'init': function(element, valueAccessor) {
184.3136 +            // Support anonymous templates
184.3137 +            var bindingValue = ko.utils.unwrapObservable(valueAccessor());
184.3138 +            if ((typeof bindingValue != "string") && (!bindingValue['name']) && (element.nodeType == 1 || element.nodeType == 8)) {
184.3139 +                // It's an anonymous template - store the element contents, then clear the element
184.3140 +                var templateNodes = element.nodeType == 1 ? element.childNodes : ko.virtualElements.childNodes(element),
184.3141 +                    container = ko.utils.moveCleanedNodesToContainerElement(templateNodes); // This also removes the nodes from their current parent
184.3142 +                new ko.templateSources.anonymousTemplate(element)['nodes'](container);
184.3143 +            }
184.3144 +            return { 'controlsDescendantBindings': true };
184.3145 +        },
184.3146 +        'update': function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
184.3147 +            var templateName = ko.utils.unwrapObservable(valueAccessor()),
184.3148 +                options = {},
184.3149 +                shouldDisplay = true,
184.3150 +                dataValue,
184.3151 +                templateComputed = null;
184.3152 +
184.3153 +            if (typeof templateName != "string") {
184.3154 +                options = templateName;
184.3155 +                templateName = options['name'];
184.3156 +
184.3157 +                // Support "if"/"ifnot" conditions
184.3158 +                if ('if' in options)
184.3159 +                    shouldDisplay = ko.utils.unwrapObservable(options['if']);
184.3160 +                if (shouldDisplay && 'ifnot' in options)
184.3161 +                    shouldDisplay = !ko.utils.unwrapObservable(options['ifnot']);
184.3162 +
184.3163 +                dataValue = ko.utils.unwrapObservable(options['data']);
184.3164 +            }
184.3165 +
184.3166 +            if ('foreach' in options) {
184.3167 +                // Render once for each data point (treating data set as empty if shouldDisplay==false)
184.3168 +                var dataArray = (shouldDisplay && options['foreach']) || [];
184.3169 +                templateComputed = ko.renderTemplateForEach(templateName || element, dataArray, options, element, bindingContext);
184.3170 +            } else if (!shouldDisplay) {
184.3171 +                ko.virtualElements.emptyNode(element);
184.3172 +            } else {
184.3173 +                // Render once for this single data point (or use the viewModel if no data was provided)
184.3174 +                var innerBindingContext = ('data' in options) ?
184.3175 +                    bindingContext['createChildContext'](dataValue, options['as']) :  // Given an explitit 'data' value, we create a child binding context for it
184.3176 +                    bindingContext;                                                        // Given no explicit 'data' value, we retain the same binding context
184.3177 +                templateComputed = ko.renderTemplate(templateName || element, innerBindingContext, options, element);
184.3178 +            }
184.3179 +
184.3180 +            // It only makes sense to have a single template computed per element (otherwise which one should have its output displayed?)
184.3181 +            disposeOldComputedAndStoreNewOne(element, templateComputed);
184.3182 +        }
184.3183 +    };
184.3184 +
184.3185 +    // Anonymous templates can't be rewritten. Give a nice error message if you try to do it.
184.3186 +    ko.expressionRewriting.bindingRewriteValidators['template'] = function(bindingValue) {
184.3187 +        var parsedBindingValue = ko.expressionRewriting.parseObjectLiteral(bindingValue);
184.3188 +
184.3189 +        if ((parsedBindingValue.length == 1) && parsedBindingValue[0]['unknown'])
184.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)
184.3191 +
184.3192 +        if (ko.expressionRewriting.keyValueArrayContainsKey(parsedBindingValue, "name"))
184.3193 +            return null; // Named templates can be rewritten, so return "no error"
184.3194 +        return "This template engine does not support anonymous templates nested within its templates";
184.3195 +    };
184.3196 +
184.3197 +    ko.virtualElements.allowedBindings['template'] = true;
184.3198 +})();
184.3199 +
184.3200 +ko.exportSymbol('setTemplateEngine', ko.setTemplateEngine);
184.3201 +ko.exportSymbol('renderTemplate', ko.renderTemplate);
184.3202 +
184.3203 +ko.utils.compareArrays = (function () {
184.3204 +    var statusNotInOld = 'added', statusNotInNew = 'deleted';
184.3205 +
184.3206 +    // Simple calculation based on Levenshtein distance.
184.3207 +    function compareArrays(oldArray, newArray, dontLimitMoves) {
184.3208 +        oldArray = oldArray || [];
184.3209 +        newArray = newArray || [];
184.3210 +
184.3211 +        if (oldArray.length <= newArray.length)
184.3212 +            return compareSmallArrayToBigArray(oldArray, newArray, statusNotInOld, statusNotInNew, dontLimitMoves);
184.3213 +        else
184.3214 +            return compareSmallArrayToBigArray(newArray, oldArray, statusNotInNew, statusNotInOld, dontLimitMoves);
184.3215 +    }
184.3216 +
184.3217 +    function compareSmallArrayToBigArray(smlArray, bigArray, statusNotInSml, statusNotInBig, dontLimitMoves) {
184.3218 +        var myMin = Math.min,
184.3219 +            myMax = Math.max,
184.3220 +            editDistanceMatrix = [],
184.3221 +            smlIndex, smlIndexMax = smlArray.length,
184.3222 +            bigIndex, bigIndexMax = bigArray.length,
184.3223 +            compareRange = (bigIndexMax - smlIndexMax) || 1,
184.3224 +            maxDistance = smlIndexMax + bigIndexMax + 1,
184.3225 +            thisRow, lastRow,
184.3226 +            bigIndexMaxForRow, bigIndexMinForRow;
184.3227 +
184.3228 +        for (smlIndex = 0; smlIndex <= smlIndexMax; smlIndex++) {
184.3229 +            lastRow = thisRow;
184.3230 +            editDistanceMatrix.push(thisRow = []);
184.3231 +            bigIndexMaxForRow = myMin(bigIndexMax, smlIndex + compareRange);
184.3232 +            bigIndexMinForRow = myMax(0, smlIndex - 1);
184.3233 +            for (bigIndex = bigIndexMinForRow; bigIndex <= bigIndexMaxForRow; bigIndex++) {
184.3234 +                if (!bigIndex)
184.3235 +                    thisRow[bigIndex] = smlIndex + 1;
184.3236 +                else if (!smlIndex)  // Top row - transform empty array into new array via additions
184.3237 +                    thisRow[bigIndex] = bigIndex + 1;
184.3238 +                else if (smlArray[smlIndex - 1] === bigArray[bigIndex - 1])
184.3239 +                    thisRow[bigIndex] = lastRow[bigIndex - 1];                  // copy value (no edit)
184.3240 +                else {
184.3241 +                    var northDistance = lastRow[bigIndex] || maxDistance;       // not in big (deletion)
184.3242 +                    var westDistance = thisRow[bigIndex - 1] || maxDistance;    // not in small (addition)
184.3243 +                    thisRow[bigIndex] = myMin(northDistance, westDistance) + 1;
184.3244 +                }
184.3245 +            }
184.3246 +        }
184.3247 +
184.3248 +        var editScript = [], meMinusOne, notInSml = [], notInBig = [];
184.3249 +        for (smlIndex = smlIndexMax, bigIndex = bigIndexMax; smlIndex || bigIndex;) {
184.3250 +            meMinusOne = editDistanceMatrix[smlIndex][bigIndex] - 1;
184.3251 +            if (bigIndex && meMinusOne === editDistanceMatrix[smlIndex][bigIndex-1]) {
184.3252 +                notInSml.push(editScript[editScript.length] = {     // added
184.3253 +                    'status': statusNotInSml,
184.3254 +                    'value': bigArray[--bigIndex],
184.3255 +                    'index': bigIndex });
184.3256 +            } else if (smlIndex && meMinusOne === editDistanceMatrix[smlIndex - 1][bigIndex]) {
184.3257 +                notInBig.push(editScript[editScript.length] = {     // deleted
184.3258 +                    'status': statusNotInBig,
184.3259 +                    'value': smlArray[--smlIndex],
184.3260 +                    'index': smlIndex });
184.3261 +            } else {
184.3262 +                editScript.push({
184.3263 +                    'status': "retained",
184.3264 +                    'value': bigArray[--bigIndex] });
184.3265 +                --smlIndex;
184.3266 +            }
184.3267 +        }
184.3268 +
184.3269 +        if (notInSml.length && notInBig.length) {
184.3270 +            // Set a limit on the number of consecutive non-matching comparisons; having it a multiple of
184.3271 +            // smlIndexMax keeps the time complexity of this algorithm linear.
184.3272 +            var limitFailedCompares = smlIndexMax * 10, failedCompares,
184.3273 +                a, d, notInSmlItem, notInBigItem;
184.3274 +            // Go through the items that have been added and deleted and try to find matches between them.
184.3275 +            for (failedCompares = a = 0; (dontLimitMoves || failedCompares < limitFailedCompares) && (notInSmlItem = notInSml[a]); a++) {
184.3276 +                for (d = 0; notInBigItem = notInBig[d]; d++) {
184.3277 +                    if (notInSmlItem['value'] === notInBigItem['value']) {
184.3278 +                        notInSmlItem['moved'] = notInBigItem['index'];
184.3279 +                        notInBigItem['moved'] = notInSmlItem['index'];
184.3280 +                        notInBig.splice(d,1);       // This item is marked as moved; so remove it from notInBig list
184.3281 +                        failedCompares = d = 0;     // Reset failed compares count because we're checking for consecutive failures
184.3282 +                        break;
184.3283 +                    }
184.3284 +                }
184.3285 +                failedCompares += d;
184.3286 +            }
184.3287 +        }
184.3288 +        return editScript.reverse();
184.3289 +    }
184.3290 +
184.3291 +    return compareArrays;
184.3292 +})();
184.3293 +
184.3294 +ko.exportSymbol('utils.compareArrays', ko.utils.compareArrays);
184.3295 +
184.3296 +(function () {
184.3297 +    // Objective:
184.3298 +    // * Given an input array, a container DOM node, and a function from array elements to arrays of DOM nodes,
184.3299 +    //   map the array elements to arrays of DOM nodes, concatenate together all these arrays, and use them to populate the container DOM node
184.3300 +    // * Next time we're given the same combination of things (with the array possibly having mutated), update the container DOM node
184.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
184.3302 +    //   previously mapped - retain those nodes, and just insert/delete other ones
184.3303 +
184.3304 +    // "callbackAfterAddingNodes" will be invoked after any "mapping"-generated nodes are inserted into the container node
184.3305 +    // You can use this, for example, to activate bindings on those nodes.
184.3306 +
184.3307 +    function fixUpNodesToBeMovedOrRemoved(contiguousNodeArray) {
184.3308 +        // Before moving, deleting, or replacing a set of nodes that were previously outputted by the "map" function, we have to reconcile
184.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,
184.3310 +        // or that new nodes might have been inserted in the middle, for example by a binding. Also, there may previously have been
184.3311 +        // leading comment nodes (created by rewritten string-based templates) that have since been removed during binding.
184.3312 +        // So, this function translates the old "map" output array into its best guess of what set of current DOM nodes should be removed.
184.3313 +        //
184.3314 +        // Rules:
184.3315 +        //   [A] Any leading nodes that aren't in the document any more should be ignored
184.3316 +        //       These most likely correspond to memoization nodes that were already removed during binding
184.3317 +        //       See https://github.com/SteveSanderson/knockout/pull/440
184.3318 +        //   [B] We want to output a contiguous series of nodes that are still in the document. So, ignore any nodes that
184.3319 +        //       have already been removed, and include any nodes that have been inserted among the previous collection
184.3320 +
184.3321 +        // Rule [A]
184.3322 +        while (contiguousNodeArray.length && !ko.utils.domNodeIsAttachedToDocument(contiguousNodeArray[0]))
184.3323 +            contiguousNodeArray.splice(0, 1);
184.3324 +
184.3325 +        // Rule [B]
184.3326 +        if (contiguousNodeArray.length > 1) {
184.3327 +            // Build up the actual new contiguous node set
184.3328 +            var current = contiguousNodeArray[0], last = contiguousNodeArray[contiguousNodeArray.length - 1], newContiguousSet = [current];
184.3329 +            while (current !== last) {
184.3330 +                current = current.nextSibling;
184.3331 +                if (!current) // Won't happen, except if the developer has manually removed some DOM elements (then we're in an undefined scenario)
184.3332 +                    return;
184.3333 +                newContiguousSet.push(current);
184.3334 +            }
184.3335 +
184.3336 +            // ... then mutate the input array to match this.
184.3337 +            // (The following line replaces the contents of contiguousNodeArray with newContiguousSet)
184.3338 +            Array.prototype.splice.apply(contiguousNodeArray, [0, contiguousNodeArray.length].concat(newContiguousSet));
184.3339 +        }
184.3340 +        return contiguousNodeArray;
184.3341 +    }
184.3342 +
184.3343 +    function mapNodeAndRefreshWhenChanged(containerNode, mapping, valueToMap, callbackAfterAddingNodes, index) {
184.3344 +        // Map this array value inside a dependentObservable so we re-map when any dependency changes
184.3345 +        var mappedNodes = [];
184.3346 +        var dependentObservable = ko.dependentObservable(function() {
184.3347 +            var newMappedNodes = mapping(valueToMap, index) || [];
184.3348 +
184.3349 +            // On subsequent evaluations, just replace the previously-inserted DOM nodes
184.3350 +            if (mappedNodes.length > 0) {
184.3351 +                ko.utils.replaceDomNodes(fixUpNodesToBeMovedOrRemoved(mappedNodes), newMappedNodes);
184.3352 +                if (callbackAfterAddingNodes)
184.3353 +                    ko.dependencyDetection.ignore(callbackAfterAddingNodes, null, [valueToMap, newMappedNodes, index]);
184.3354 +            }
184.3355 +
184.3356 +            // Replace the contents of the mappedNodes array, thereby updating the record
184.3357 +            // of which nodes would be deleted if valueToMap was itself later removed
184.3358 +            mappedNodes.splice(0, mappedNodes.length);
184.3359 +            ko.utils.arrayPushAll(mappedNodes, newMappedNodes);
184.3360 +        }, null, { disposeWhenNodeIsRemoved: containerNode, disposeWhen: function() { return (mappedNodes.length == 0) || !ko.utils.domNodeIsAttachedToDocument(mappedNodes[0]) } });
184.3361 +        return { mappedNodes : mappedNodes, dependentObservable : (dependentObservable.isActive() ? dependentObservable : undefined) };
184.3362 +    }
184.3363 +
184.3364 +    var lastMappingResultDomDataKey = "setDomNodeChildrenFromArrayMapping_lastMappingResult";
184.3365 +
184.3366 +    ko.utils.setDomNodeChildrenFromArrayMapping = function (domNode, array, mapping, options, callbackAfterAddingNodes) {
184.3367 +        // Compare the provided array against the previous one
184.3368 +        array = array || [];
184.3369 +        options = options || {};
184.3370 +        var isFirstExecution = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) === undefined;
184.3371 +        var lastMappingResult = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) || [];
184.3372 +        var lastArray = ko.utils.arrayMap(lastMappingResult, function (x) { return x.arrayEntry; });
184.3373 +        var editScript = ko.utils.compareArrays(lastArray, array);
184.3374 +
184.3375 +        // Build the new mapping result
184.3376 +        var newMappingResult = [];
184.3377 +        var lastMappingResultIndex = 0;
184.3378 +        var newMappingResultIndex = 0;
184.3379 +
184.3380 +        var nodesToDelete = [];
184.3381 +        var itemsToProcess = [];
184.3382 +        var itemsForBeforeRemoveCallbacks = [];
184.3383 +        var itemsForMoveCallbacks = [];
184.3384 +        var itemsForAfterAddCallbacks = [];
184.3385 +        var mapData;
184.3386 +
184.3387 +        function itemMovedOrRetained(editScriptIndex, oldPosition) {
184.3388 +            mapData = lastMappingResult[oldPosition];
184.3389 +            if (newMappingResultIndex !== oldPosition)
184.3390 +                itemsForMoveCallbacks[editScriptIndex] = mapData;
184.3391 +            // Since updating the index might change the nodes, do so before calling fixUpNodesToBeMovedOrRemoved
184.3392 +            mapData.indexObservable(newMappingResultIndex++);
184.3393 +            fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes);
184.3394 +            newMappingResult.push(mapData);
184.3395 +            itemsToProcess.push(mapData);
184.3396 +        }
184.3397 +
184.3398 +        function callCallback(callback, items) {
184.3399 +            if (callback) {
184.3400 +                for (var i = 0, n = items.length; i < n; i++) {
184.3401 +                    if (items[i]) {
184.3402 +                        ko.utils.arrayForEach(items[i].mappedNodes, function(node) {
184.3403 +                            callback(node, i, items[i].arrayEntry);
184.3404 +                        });
184.3405 +                    }
184.3406 +                }
184.3407 +            }
184.3408 +        }
184.3409 +
184.3410 +        for (var i = 0, editScriptItem, movedIndex; editScriptItem = editScript[i]; i++) {
184.3411 +            movedIndex = editScriptItem['moved'];
184.3412 +            switch (editScriptItem['status']) {
184.3413 +                case "deleted":
184.3414 +                    if (movedIndex === undefined) {
184.3415 +                        mapData = lastMappingResult[lastMappingResultIndex];
184.3416 +
184.3417 +                        // Stop tracking changes to the mapping for these nodes
184.3418 +                        if (mapData.dependentObservable)
184.3419 +                            mapData.dependentObservable.dispose();
184.3420 +
184.3421 +                        // Queue these nodes for later removal
184.3422 +                        nodesToDelete.push.apply(nodesToDelete, fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes));
184.3423 +                        if (options['beforeRemove']) {
184.3424 +                            itemsForBeforeRemoveCallbacks[i] = mapData;
184.3425 +                            itemsToProcess.push(mapData);
184.3426 +                        }
184.3427 +                    }
184.3428 +                    lastMappingResultIndex++;
184.3429 +                    break;
184.3430 +
184.3431 +                case "retained":
184.3432 +                    itemMovedOrRetained(i, lastMappingResultIndex++);
184.3433 +                    break;
184.3434 +
184.3435 +                case "added":
184.3436 +                    if (movedIndex !== undefined) {
184.3437 +                        itemMovedOrRetained(i, movedIndex);
184.3438 +                    } else {
184.3439 +                        mapData = { arrayEntry: editScriptItem['value'], indexObservable: ko.observable(newMappingResultIndex++) };
184.3440 +                        newMappingResult.push(mapData);
184.3441 +                        itemsToProcess.push(mapData);
184.3442 +                        if (!isFirstExecution)
184.3443 +                            itemsForAfterAddCallbacks[i] = mapData;
184.3444 +                    }
184.3445 +                    break;
184.3446 +            }
184.3447 +        }
184.3448 +
184.3449 +        // Call beforeMove first before any changes have been made to the DOM
184.3450 +        callCallback(options['beforeMove'], itemsForMoveCallbacks);
184.3451 +
184.3452 +        // Next remove nodes for deleted items (or just clean if there's a beforeRemove callback)
184.3453 +        ko.utils.arrayForEach(nodesToDelete, options['beforeRemove'] ? ko.cleanNode : ko.removeNode);
184.3454 +
184.3455 +        // Next add/reorder the remaining items (will include deleted items if there's a beforeRemove callback)
184.3456 +        for (var i = 0, nextNode = ko.virtualElements.firstChild(domNode), lastNode, node; mapData = itemsToProcess[i]; i++) {
184.3457 +            // Get nodes for newly added items
184.3458 +            if (!mapData.mappedNodes)
184.3459 +                ko.utils.extend(mapData, mapNodeAndRefreshWhenChanged(domNode, mapping, mapData.arrayEntry, callbackAfterAddingNodes, mapData.indexObservable));
184.3460 +
184.3461 +            // Put nodes in the right place if they aren't there already
184.3462 +            for (var j = 0; node = mapData.mappedNodes[j]; nextNode = node.nextSibling, lastNode = node, j++) {
184.3463 +                if (node !== nextNode)
184.3464 +                    ko.virtualElements.insertAfter(domNode, node, lastNode);
184.3465 +            }
184.3466 +
184.3467 +            // Run the callbacks for newly added nodes (for example, to apply bindings, etc.)
184.3468 +            if (!mapData.initialized && callbackAfterAddingNodes) {
184.3469 +                callbackAfterAddingNodes(mapData.arrayEntry, mapData.mappedNodes, mapData.indexObservable);
184.3470 +                mapData.initialized = true;
184.3471 +            }
184.3472 +        }
184.3473 +
184.3474 +        // If there's a beforeRemove callback, call it after reordering.
184.3475 +        // Note that we assume that the beforeRemove callback will usually be used to remove the nodes using
184.3476 +        // some sort of animation, which is why we first reorder the nodes that will be removed. If the
184.3477 +        // callback instead removes the nodes right away, it would be more efficient to skip reordering them.
184.3478 +        // Perhaps we'll make that change in the future if this scenario becomes more common.
184.3479 +        callCallback(options['beforeRemove'], itemsForBeforeRemoveCallbacks);
184.3480 +
184.3481 +        // Finally call afterMove and afterAdd callbacks
184.3482 +        callCallback(options['afterMove'], itemsForMoveCallbacks);
184.3483 +        callCallback(options['afterAdd'], itemsForAfterAddCallbacks);
184.3484 +
184.3485 +        // Store a copy of the array items we just considered so we can difference it next time
184.3486 +        ko.utils.domData.set(domNode, lastMappingResultDomDataKey, newMappingResult);
184.3487 +    }
184.3488 +})();
184.3489 +
184.3490 +ko.exportSymbol('utils.setDomNodeChildrenFromArrayMapping', ko.utils.setDomNodeChildrenFromArrayMapping);
184.3491 +ko.nativeTemplateEngine = function () {
184.3492 +    this['allowTemplateRewriting'] = false;
184.3493 +}
184.3494 +
184.3495 +ko.nativeTemplateEngine.prototype = new ko.templateEngine();
184.3496 +ko.nativeTemplateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
184.3497 +    var useNodesIfAvailable = !(ko.utils.ieVersion < 9), // IE<9 cloneNode doesn't work properly
184.3498 +        templateNodesFunc = useNodesIfAvailable ? templateSource['nodes'] : null,
184.3499 +        templateNodes = templateNodesFunc ? templateSource['nodes']() : null;
184.3500 +
184.3501 +    if (templateNodes) {
184.3502 +        return ko.utils.makeArray(templateNodes.cloneNode(true).childNodes);
184.3503 +    } else {
184.3504 +        var templateText = templateSource['text']();
184.3505 +        return ko.utils.parseHtmlFragment(templateText);
184.3506 +    }
184.3507 +};
184.3508 +
184.3509 +ko.nativeTemplateEngine.instance = new ko.nativeTemplateEngine();
184.3510 +ko.setTemplateEngine(ko.nativeTemplateEngine.instance);
184.3511 +
184.3512 +ko.exportSymbol('nativeTemplateEngine', ko.nativeTemplateEngine);
184.3513 +(function() {
184.3514 +    ko.jqueryTmplTemplateEngine = function () {
184.3515 +        // Detect which version of jquery-tmpl you're using. Unfortunately jquery-tmpl
184.3516 +        // doesn't expose a version number, so we have to infer it.
184.3517 +        // Note that as of Knockout 1.3, we only support jQuery.tmpl 1.0.0pre and later,
184.3518 +        // which KO internally refers to as version "2", so older versions are no longer detected.
184.3519 +        var jQueryTmplVersion = this.jQueryTmplVersion = (function() {
184.3520 +            if ((typeof(jQuery) == "undefined") || !(jQuery['tmpl']))
184.3521 +                return 0;
184.3522 +            // Since it exposes no official version number, we use our own numbering system. To be updated as jquery-tmpl evolves.
184.3523 +            try {
184.3524 +                if (jQuery['tmpl']['tag']['tmpl']['open'].toString().indexOf('__') >= 0) {
184.3525 +                    // Since 1.0.0pre, custom tags should append markup to an array called "__"
184.3526 +                    return 2; // Final version of jquery.tmpl
184.3527 +                }
184.3528 +            } catch(ex) { /* Apparently not the version we were looking for */ }
184.3529 +
184.3530 +            return 1; // Any older version that we don't support
184.3531 +        })();
184.3532 +
184.3533 +        function ensureHasReferencedJQueryTemplates() {
184.3534 +            if (jQueryTmplVersion < 2)
184.3535 +                throw new Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");
184.3536 +        }
184.3537 +
184.3538 +        function executeTemplate(compiledTemplate, data, jQueryTemplateOptions) {
184.3539 +            return jQuery['tmpl'](compiledTemplate, data, jQueryTemplateOptions);
184.3540 +        }
184.3541 +
184.3542 +        this['renderTemplateSource'] = function(templateSource, bindingContext, options) {
184.3543 +            options = options || {};
184.3544 +            ensureHasReferencedJQueryTemplates();
184.3545 +
184.3546 +            // Ensure we have stored a precompiled version of this template (don't want to reparse on every render)
184.3547 +            var precompiled = templateSource['data']('precompiled');
184.3548 +            if (!precompiled) {
184.3549 +                var templateText = templateSource['text']() || "";
184.3550 +                // Wrap in "with($whatever.koBindingContext) { ... }"
184.3551 +                templateText = "{{ko_with $item.koBindingContext}}" + templateText + "{{/ko_with}}";
184.3552 +
184.3553 +                precompiled = jQuery['template'](null, templateText);
184.3554 +                templateSource['data']('precompiled', precompiled);
184.3555 +            }
184.3556 +
184.3557 +            var data = [bindingContext['$data']]; // Prewrap the data in an array to stop jquery.tmpl from trying to unwrap any arrays
184.3558 +            var jQueryTemplateOptions = jQuery['extend']({ 'koBindingContext': bindingContext }, options['templateOptions']);
184.3559 +
184.3560 +            var resultNodes = executeTemplate(precompiled, data, jQueryTemplateOptions);
184.3561 +            resultNodes['appendTo'](document.createElement("div")); // Using "appendTo" forces jQuery/jQuery.tmpl to perform necessary cleanup work
184.3562 +
184.3563 +            jQuery['fragments'] = {}; // Clear jQuery's fragment cache to avoid a memory leak after a large number of template renders
184.3564 +            return resultNodes;
184.3565 +        };
184.3566 +
184.3567 +        this['createJavaScriptEvaluatorBlock'] = function(script) {
184.3568 +            return "{{ko_code ((function() { return " + script + " })()) }}";
184.3569 +        };
184.3570 +
184.3571 +        this['addTemplate'] = function(templateName, templateMarkup) {
184.3572 +            document.write("<script type='text/html' id='" + templateName + "'>" + templateMarkup + "</script>");
184.3573 +        };
184.3574 +
184.3575 +        if (jQueryTmplVersion > 0) {
184.3576 +            jQuery['tmpl']['tag']['ko_code'] = {
184.3577 +                open: "__.push($1 || '');"
184.3578 +            };
184.3579 +            jQuery['tmpl']['tag']['ko_with'] = {
184.3580 +                open: "with($1) {",
184.3581 +                close: "} "
184.3582 +            };
184.3583 +        }
184.3584 +    };
184.3585 +
184.3586 +    ko.jqueryTmplTemplateEngine.prototype = new ko.templateEngine();
184.3587 +
184.3588 +    // Use this one by default *only if jquery.tmpl is referenced*
184.3589 +    var jqueryTmplTemplateEngineInstance = new ko.jqueryTmplTemplateEngine();
184.3590 +    if (jqueryTmplTemplateEngineInstance.jQueryTmplVersion > 0)
184.3591 +        ko.setTemplateEngine(jqueryTmplTemplateEngineInstance);
184.3592 +
184.3593 +    ko.exportSymbol('jqueryTmplTemplateEngine', ko.jqueryTmplTemplateEngine);
184.3594 +})();
184.3595 +});
184.3596 +})(window,document,navigator,window["jQuery"]);
184.3597 +})();
184.3598 \ No newline at end of file
   185.1 --- a/ko-fx/src/test/java/org/apidesign/html/kofx/DynamicHTTP.java	Mon Dec 16 17:16:02 2013 +0100
   185.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   185.3 @@ -1,237 +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.ByteArrayInputStream;
  185.27 -import java.io.ByteArrayOutputStream;
  185.28 -import java.io.IOException;
  185.29 -import java.io.InputStream;
  185.30 -import java.io.OutputStream;
  185.31 -import java.io.Reader;
  185.32 -import java.net.URI;
  185.33 -import java.net.URISyntaxException;
  185.34 -import java.util.ArrayList;
  185.35 -import java.util.List;
  185.36 -import java.util.logging.Level;
  185.37 -import java.util.logging.Logger;
  185.38 -import org.glassfish.grizzly.PortRange;
  185.39 -import org.glassfish.grizzly.http.server.HttpHandler;
  185.40 -import org.glassfish.grizzly.http.server.HttpServer;
  185.41 -import org.glassfish.grizzly.http.server.NetworkListener;
  185.42 -import org.glassfish.grizzly.http.server.Request;
  185.43 -import org.glassfish.grizzly.http.server.Response;
  185.44 -import org.glassfish.grizzly.http.server.ServerConfiguration;
  185.45 -import org.glassfish.grizzly.websockets.WebSocket;
  185.46 -import org.glassfish.grizzly.websockets.WebSocketAddOn;
  185.47 -import org.glassfish.grizzly.websockets.WebSocketApplication;
  185.48 -import org.glassfish.grizzly.websockets.WebSocketEngine;
  185.49 -
  185.50 -/**
  185.51 - *
  185.52 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  185.53 - */
  185.54 -final class DynamicHTTP extends HttpHandler {
  185.55 -    private static final Logger LOG = Logger.getLogger(DynamicHTTP.class.getName());
  185.56 -    private static int resourcesCount;
  185.57 -    private static List<Resource> resources;
  185.58 -    private static ServerConfiguration conf;
  185.59 -    private static HttpServer server;
  185.60 -    
  185.61 -    private DynamicHTTP() {
  185.62 -    }
  185.63 -    
  185.64 -    static URI initServer() throws Exception {
  185.65 -        server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
  185.66 -        final WebSocketAddOn addon = new WebSocketAddOn();
  185.67 -        for (NetworkListener listener : server.getListeners()) {
  185.68 -            listener.registerAddOn(addon);
  185.69 -        }        
  185.70 -        resources = new ArrayList<Resource>();
  185.71 -
  185.72 -        conf = server.getServerConfiguration();
  185.73 -        final DynamicHTTP dh = new DynamicHTTP();
  185.74 -
  185.75 -        conf.addHttpHandler(dh, "/");
  185.76 -        
  185.77 -        server.start();
  185.78 -
  185.79 -        return pageURL("http", server, "/test.html");
  185.80 -    }
  185.81 -    
  185.82 -    @Override
  185.83 -    public void service(Request request, Response response) throws Exception {
  185.84 -        if ("/test.html".equals(request.getRequestURI())) {
  185.85 -            response.setContentType("text/html");
  185.86 -            final InputStream is = DynamicHTTP.class.getResourceAsStream("test.html");
  185.87 -            copyStream(is, response.getOutputStream(), null);
  185.88 -            return;
  185.89 -        }
  185.90 -        if ("/dynamic".equals(request.getRequestURI())) {
  185.91 -            String mimeType = request.getParameter("mimeType");
  185.92 -            List<String> params = new ArrayList<String>();
  185.93 -            boolean webSocket = false;
  185.94 -            for (int i = 0;; i++) {
  185.95 -                String p = request.getParameter("param" + i);
  185.96 -                if (p == null) {
  185.97 -                    break;
  185.98 -                }
  185.99 -                if ("protocol:ws".equals(p)) {
 185.100 -                    webSocket = true;
 185.101 -                    continue;
 185.102 -                }
 185.103 -                params.add(p);
 185.104 -            }
 185.105 -            final String cnt = request.getParameter("content");
 185.106 -            String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
 185.107 -            ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
 185.108 -            URI url;
 185.109 -            final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
 185.110 -            if (webSocket) {
 185.111 -                url = registerWebSocket(res);
 185.112 -            } else {
 185.113 -                url = registerResource(res);
 185.114 -            }
 185.115 -            response.getWriter().write(url.toString());
 185.116 -            response.getWriter().write("\n");
 185.117 -            return;
 185.118 -        }
 185.119 -
 185.120 -        for (Resource r : resources) {
 185.121 -            if (r.httpPath.equals(request.getRequestURI())) {
 185.122 -                response.setContentType(r.httpType);
 185.123 -                r.httpContent.reset();
 185.124 -                String[] params = null;
 185.125 -                if (r.parameters.length != 0) {
 185.126 -                    params = new String[r.parameters.length];
 185.127 -                    for (int i = 0; i < r.parameters.length; i++) {
 185.128 -                        params[i] = request.getParameter(r.parameters[i]);
 185.129 -                        if (params[i] == null) {
 185.130 -                            if ("http.method".equals(r.parameters[i])) {
 185.131 -                                params[i] = request.getMethod().toString();
 185.132 -                            } else if ("http.requestBody".equals(r.parameters[i])) {
 185.133 -                                Reader rdr = request.getReader();
 185.134 -                                StringBuilder sb = new StringBuilder();
 185.135 -                                for (;;) {
 185.136 -                                    int ch = rdr.read();
 185.137 -                                    if (ch == -1) {
 185.138 -                                        break;
 185.139 -                                    }
 185.140 -                                    sb.append((char) ch);
 185.141 -                                }
 185.142 -                                params[i] = sb.toString();
 185.143 -                            }
 185.144 -                        }
 185.145 -                        if (params[i] == null) {
 185.146 -                            params[i] = "null";
 185.147 -                        }
 185.148 -                    }
 185.149 -                }
 185.150 -
 185.151 -                copyStream(r.httpContent, response.getOutputStream(), null, params);
 185.152 -            }
 185.153 -        }
 185.154 -    }
 185.155 -    
 185.156 -    private URI registerWebSocket(Resource r) {
 185.157 -        WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
 185.158 -        return pageURL("ws", server, r.httpPath);
 185.159 -    }
 185.160 -
 185.161 -    private URI registerResource(Resource r) {
 185.162 -        if (!resources.contains(r)) {
 185.163 -            resources.add(r);
 185.164 -            conf.addHttpHandler(this, r.httpPath);
 185.165 -        }
 185.166 -        return pageURL("http", server, r.httpPath);
 185.167 -    }
 185.168 -    
 185.169 -    private static URI pageURL(String proto, HttpServer server, final String page) {
 185.170 -        NetworkListener listener = server.getListeners().iterator().next();
 185.171 -        int port = listener.getPort();
 185.172 -        try {
 185.173 -            return new URI(proto + "://localhost:" + port + page);
 185.174 -        } catch (URISyntaxException ex) {
 185.175 -            throw new IllegalStateException(ex);
 185.176 -        }
 185.177 -    }
 185.178 -    
 185.179 -    static final class Resource {
 185.180 -
 185.181 -        final InputStream httpContent;
 185.182 -        final String httpType;
 185.183 -        final String httpPath;
 185.184 -        final String[] parameters;
 185.185 -
 185.186 -        Resource(InputStream httpContent, String httpType, String httpPath,
 185.187 -            String[] parameters) {
 185.188 -            httpContent.mark(Integer.MAX_VALUE);
 185.189 -            this.httpContent = httpContent;
 185.190 -            this.httpType = httpType;
 185.191 -            this.httpPath = httpPath;
 185.192 -            this.parameters = parameters;
 185.193 -        }
 185.194 -    }
 185.195 -
 185.196 -    static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
 185.197 -        for (;;) {
 185.198 -            int ch = is.read();
 185.199 -            if (ch == -1) {
 185.200 -                break;
 185.201 -            }
 185.202 -            if (ch == '$' && params.length > 0) {
 185.203 -                int cnt = is.read() - '0';
 185.204 -                if (baseURL != null && cnt == 'U' - '0') {
 185.205 -                    os.write(baseURL.getBytes("UTF-8"));
 185.206 -                } else {
 185.207 -                    if (cnt >= 0 && cnt < params.length) {
 185.208 -                        os.write(params[cnt].getBytes("UTF-8"));
 185.209 -                    } else {
 185.210 -                        os.write('$');
 185.211 -                        os.write(cnt + '0');
 185.212 -                    }
 185.213 -                }
 185.214 -            } else {
 185.215 -                os.write(ch);
 185.216 -            }
 185.217 -        }
 185.218 -    }
 185.219 -    
 185.220 -    private static class WS extends WebSocketApplication {
 185.221 -        private final Resource r;
 185.222 -
 185.223 -        private WS(Resource r) {
 185.224 -            this.r = r;
 185.225 -        }
 185.226 -
 185.227 -        @Override
 185.228 -        public void onMessage(WebSocket socket, String text) {
 185.229 -            try {
 185.230 -                r.httpContent.reset();
 185.231 -                ByteArrayOutputStream out = new ByteArrayOutputStream();
 185.232 -                copyStream(r.httpContent, out, null, text);
 185.233 -                String s = new String(out.toByteArray(), "UTF-8");
 185.234 -                socket.send(s);
 185.235 -            } catch (IOException ex) {
 185.236 -                LOG.log(Level.WARNING, "Error processing message " + text, ex);
 185.237 -            }
 185.238 -        }
 185.239 -    }
 185.240 -}
   186.1 --- a/ko-fx/src/test/java/org/apidesign/html/kofx/KOFx.java	Mon Dec 16 17:16:02 2013 +0100
   186.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   186.3 @@ -1,96 +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 java.io.Closeable;
  186.27 -import java.lang.reflect.InvocationTargetException;
  186.28 -import java.lang.reflect.Method;
  186.29 -import javafx.application.Platform;
  186.30 -import org.apidesign.html.boot.spi.Fn;
  186.31 -import org.testng.ITest;
  186.32 -import org.testng.annotations.Test;
  186.33 -
  186.34 -/**
  186.35 - *
  186.36 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  186.37 - */
  186.38 -public final class KOFx implements ITest, Runnable {
  186.39 -    private final Fn.Presenter p;
  186.40 -    private final Method m;
  186.41 -    private Object result;
  186.42 -    private Object inst;
  186.43 -    private int count;
  186.44 -
  186.45 -    KOFx(Fn.Presenter p, Method m) {
  186.46 -        this.p = p;
  186.47 -        this.m = m;
  186.48 -    }
  186.49 -
  186.50 -    @Override
  186.51 -    public String getTestName() {
  186.52 -        return m.getName();
  186.53 -    }
  186.54 -
  186.55 -    @Test
  186.56 -    public synchronized void executeTest() throws Exception {
  186.57 -        if (result == null) {
  186.58 -            Platform.runLater(this);
  186.59 -            wait();
  186.60 -        }
  186.61 -        if (result instanceof Exception) {
  186.62 -            throw (Exception)result;
  186.63 -        }
  186.64 -        if (result instanceof Error) {
  186.65 -            throw (Error)result;
  186.66 -        }
  186.67 -    }
  186.68 -
  186.69 -    @Override
  186.70 -    public synchronized void run() {
  186.71 -        boolean notify = true;
  186.72 -        try (Closeable a = Fn.activate(p)) {
  186.73 -            if (inst == null) {
  186.74 -                inst = m.getDeclaringClass().newInstance();
  186.75 -            }
  186.76 -            result = m.invoke(inst);
  186.77 -            if (result == null) {
  186.78 -                result = this;
  186.79 -            }
  186.80 -        } catch (InvocationTargetException ex) {
  186.81 -            Throwable r = ex.getTargetException();
  186.82 -            if (r instanceof InterruptedException) {
  186.83 -                if (count++ < 10000) {
  186.84 -                    notify = false;
  186.85 -                    Platform.runLater(this);
  186.86 -                    return;
  186.87 -                }
  186.88 -            }
  186.89 -            result = r;
  186.90 -        } catch (Exception ex) {
  186.91 -            result = ex;
  186.92 -        } finally {
  186.93 -            if (notify) {
  186.94 -                notifyAll();
  186.95 -            }
  186.96 -        }
  186.97 -    }
  186.98 -    
  186.99 -}
   187.1 --- a/ko-fx/src/test/java/org/apidesign/html/kofx/KnockoutFXTest.java	Mon Dec 16 17:16:02 2013 +0100
   187.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   187.3 @@ -1,207 +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.BufferedReader;
  187.27 -import java.io.IOException;
  187.28 -import java.io.InputStreamReader;
  187.29 -import java.lang.annotation.Annotation;
  187.30 -import java.lang.reflect.Method;
  187.31 -import java.net.URI;
  187.32 -import java.net.URISyntaxException;
  187.33 -import java.net.URL;
  187.34 -import java.net.URLConnection;
  187.35 -import java.util.ArrayList;
  187.36 -import java.util.List;
  187.37 -import java.util.Map;
  187.38 -import java.util.concurrent.Executors;
  187.39 -import net.java.html.BrwsrCtx;
  187.40 -import net.java.html.boot.BrowserBuilder;
  187.41 -import net.java.html.js.JavaScriptBody;
  187.42 -import org.apidesign.html.boot.impl.FnContext;
  187.43 -import org.apidesign.html.boot.spi.Fn;
  187.44 -import org.apidesign.html.context.spi.Contexts;
  187.45 -import org.apidesign.html.json.spi.Technology;
  187.46 -import org.apidesign.html.json.spi.Transfer;
  187.47 -import org.apidesign.html.json.spi.WSTransfer;
  187.48 -import org.apidesign.html.json.tck.KOTest;
  187.49 -import org.apidesign.html.json.tck.KnockoutTCK;
  187.50 -import org.json.JSONException;
  187.51 -import org.json.JSONObject;
  187.52 -import org.openide.util.lookup.ServiceProvider;
  187.53 -import org.testng.annotations.Factory;
  187.54 -import static org.testng.Assert.*;
  187.55 -
  187.56 -/**
  187.57 - *
  187.58 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  187.59 - */
  187.60 -@ServiceProvider(service = KnockoutTCK.class)
  187.61 -public final class KnockoutFXTest extends KnockoutTCK {
  187.62 -    private static Class<?> browserClass;
  187.63 -    private static Fn.Presenter browserContext;
  187.64 -    
  187.65 -    public KnockoutFXTest() {
  187.66 -    }
  187.67 -    
  187.68 -    @Factory public static Object[] compatibilityTests() throws Exception {
  187.69 -        Class[] arr = testClasses();
  187.70 -        for (int i = 0; i < arr.length; i++) {
  187.71 -            assertEquals(
  187.72 -                arr[i].getClassLoader(),
  187.73 -                KnockoutFXTest.class.getClassLoader(),
  187.74 -                "All classes loaded by the same classloader"
  187.75 -            );
  187.76 -        }
  187.77 -        
  187.78 -        URI uri = DynamicHTTP.initServer();
  187.79 -    
  187.80 -        final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(KnockoutFXTest.class).
  187.81 -            loadPage(uri.toString()).
  187.82 -            invoke("initialized");
  187.83 -        
  187.84 -        Executors.newSingleThreadExecutor().submit(new Runnable() {
  187.85 -            @Override
  187.86 -            public void run() {
  187.87 -                bb.showAndWait();
  187.88 -            }
  187.89 -        });
  187.90 -        
  187.91 -        ClassLoader l = getClassLoader();
  187.92 -        List<Object> res = new ArrayList<Object>();
  187.93 -        for (int i = 0; i < arr.length; i++) {
  187.94 -            Class<?> c = Class.forName(arr[i].getName(), true, l);
  187.95 -            seekKOTests(c, res);
  187.96 -        }
  187.97 -        Class<?> c = Class.forName(LessCallbacksCheck.class.getName(), true, l);
  187.98 -        seekKOTests(c, res);
  187.99 -        return res.toArray();
 187.100 -    }
 187.101 -
 187.102 -    private static void seekKOTests(Class<?> c, List<Object> res) throws SecurityException, ClassNotFoundException {
 187.103 -        Class<? extends Annotation> koTest =
 187.104 -            c.getClassLoader().loadClass(KOTest.class.getName()).
 187.105 -            asSubclass(Annotation.class);
 187.106 -        for (Method m : c.getMethods()) {
 187.107 -            if (m.getAnnotation(koTest) != null) {
 187.108 -                res.add(new KOFx(browserContext, m));
 187.109 -            }
 187.110 -        }
 187.111 -    }
 187.112 -
 187.113 -    static synchronized ClassLoader getClassLoader() throws InterruptedException {
 187.114 -        while (browserClass == null) {
 187.115 -            KnockoutFXTest.class.wait();
 187.116 -        }
 187.117 -        return browserClass.getClassLoader();
 187.118 -    }
 187.119 -    
 187.120 -    public static synchronized void initialized(Class<?> browserCls) throws Exception {
 187.121 -        browserClass = browserCls;
 187.122 -        browserContext = FnContext.currentPresenter();
 187.123 -        KnockoutFXTest.class.notifyAll();
 187.124 -    }
 187.125 -    
 187.126 -    public static void initialized() throws Exception {
 187.127 -        Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(KnockoutFXTest.class.getName());
 187.128 -        Method m = classpathClass.getMethod("initialized", Class.class);
 187.129 -        m.invoke(null, KnockoutFXTest.class);
 187.130 -        browserContext = FnContext.currentPresenter();
 187.131 -    }
 187.132 -    
 187.133 -    @Override
 187.134 -    public BrwsrCtx createContext() {
 187.135 -        FXContext fx = new FXContext(browserContext);
 187.136 -        Contexts.Builder cb = Contexts.newBuilder().
 187.137 -            register(Technology.class, fx, 10).
 187.138 -            register(Transfer.class, fx, 10);
 187.139 -        if (fx.areWebSocketsSupported()) {
 187.140 -            cb.register(WSTransfer.class, fx, 10);
 187.141 -        }
 187.142 -        return cb.build();
 187.143 -    }
 187.144 -
 187.145 -    @Override
 187.146 -    public Object createJSON(Map<String, Object> values) {
 187.147 -        JSONObject json = new JSONObject();
 187.148 -        for (Map.Entry<String, Object> entry : values.entrySet()) {
 187.149 -            try {
 187.150 -                json.put(entry.getKey(), entry.getValue());
 187.151 -            } catch (JSONException ex) {
 187.152 -                throw new IllegalStateException(ex);
 187.153 -            }
 187.154 -        }
 187.155 -        return json;
 187.156 -    }
 187.157 -
 187.158 -    @Override
 187.159 -    @JavaScriptBody(args = { "s", "args" }, body = ""
 187.160 -        + "var f = new Function(s); "
 187.161 -        + "return f.apply(null, args);"
 187.162 -    )
 187.163 -    public native Object executeScript(String script, Object[] arguments);
 187.164 -
 187.165 -    @JavaScriptBody(args = {  }, body = 
 187.166 -          "var h;"
 187.167 -        + "if (!!window && !!window.location && !!window.location.href)\n"
 187.168 -        + "  h = window.location.href;\n"
 187.169 -        + "else "
 187.170 -        + "  h = null;"
 187.171 -        + "return h;\n"
 187.172 -    )
 187.173 -    private static native String findBaseURL();
 187.174 -    
 187.175 -    @Override
 187.176 -    public URI prepareURL(String content, String mimeType, String[] parameters) {
 187.177 -        try {
 187.178 -            final URL baseURL = new URL(findBaseURL());
 187.179 -            StringBuilder sb = new StringBuilder();
 187.180 -            sb.append("/dynamic?mimeType=").append(mimeType);
 187.181 -            for (int i = 0; i < parameters.length; i++) {
 187.182 -                sb.append("&param" + i).append("=").append(parameters[i]);
 187.183 -            }
 187.184 -            String mangle = content.replace("\n", "%0a")
 187.185 -                .replace("\"", "\\\"").replace(" ", "%20");
 187.186 -            sb.append("&content=").append(mangle);
 187.187 -
 187.188 -            URL query = new URL(baseURL, sb.toString());
 187.189 -            URLConnection c = query.openConnection();
 187.190 -            BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
 187.191 -            URI connectTo = new URI(br.readLine());
 187.192 -            return connectTo;
 187.193 -        } catch (IOException ex) {
 187.194 -            throw new IllegalStateException(ex);
 187.195 -        } catch (URISyntaxException ex) {
 187.196 -            throw new IllegalStateException(ex);
 187.197 -        }
 187.198 -    }
 187.199 -
 187.200 -    @Override
 187.201 -    public boolean canFailWebSocketTest() {
 187.202 -        try {
 187.203 -            Class.forName("java.util.function.Function");
 187.204 -            return false;
 187.205 -        } catch (ClassNotFoundException ex) {
 187.206 -            // running on JDK7, FX WebView WebSocket impl does not work
 187.207 -            return true;
 187.208 -        }
 187.209 -    }
 187.210 -}
   188.1 --- a/ko-fx/src/test/java/org/apidesign/html/kofx/LessCallbacksCheck.java	Mon Dec 16 17:16:02 2013 +0100
   188.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   188.3 @@ -1,60 +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 java.io.PrintWriter;
  188.27 -import java.io.StringWriter;
  188.28 -import net.java.html.json.ComputedProperty;
  188.29 -import net.java.html.json.Model;
  188.30 -import net.java.html.json.Property;
  188.31 -import org.apidesign.html.json.tck.KOTest;
  188.32 -
  188.33 -/**
  188.34 - *
  188.35 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  188.36 - */
  188.37 -@Model(className = "LessCalls", properties = {
  188.38 -    @Property(name = "value", type = int.class)
  188.39 -})
  188.40 -public class LessCallbacksCheck {
  188.41 -    private static StringWriter sw;
  188.42 -    
  188.43 -    @ComputedProperty static int plusOne(int value) {
  188.44 -        if (sw == null) {
  188.45 -            sw = new StringWriter();
  188.46 -        }
  188.47 -        new Exception("Who calls me?").printStackTrace(
  188.48 -            new PrintWriter(sw)
  188.49 -        );
  188.50 -        return value + 1;
  188.51 -    }
  188.52 -    
  188.53 -    @KOTest public void dontCallForInitialValueBackToJavaVM() {
  188.54 -        LessCalls m = new LessCalls(10).applyBindings();
  188.55 -        assert m.getPlusOne() == 11 : "Expecting 11: " + m.getPlusOne();
  188.56 -        
  188.57 -        assert sw != null : "StringWriter should be initialized: " + sw;
  188.58 -        
  188.59 -        if (sw.toString().contains("$JsCallbacks$")) {
  188.60 -            assert false : "Don't call for initial value via JsCallbacks:\n" + sw;
  188.61 -        }
  188.62 -    }
  188.63 -}
   189.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   189.2 +++ b/ko-fx/src/test/java/org/netbeans/html/kofx/DynamicHTTP.java	Mon Dec 16 17:16:40 2013 +0100
   189.3 @@ -0,0 +1,259 @@
   189.4 +/**
   189.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   189.6 + *
   189.7 + * Copyright 1997-2010 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.io.ByteArrayInputStream;
  189.49 +import java.io.ByteArrayOutputStream;
  189.50 +import java.io.IOException;
  189.51 +import java.io.InputStream;
  189.52 +import java.io.OutputStream;
  189.53 +import java.io.Reader;
  189.54 +import java.net.URI;
  189.55 +import java.net.URISyntaxException;
  189.56 +import java.util.ArrayList;
  189.57 +import java.util.List;
  189.58 +import java.util.logging.Level;
  189.59 +import java.util.logging.Logger;
  189.60 +import org.glassfish.grizzly.PortRange;
  189.61 +import org.glassfish.grizzly.http.server.HttpHandler;
  189.62 +import org.glassfish.grizzly.http.server.HttpServer;
  189.63 +import org.glassfish.grizzly.http.server.NetworkListener;
  189.64 +import org.glassfish.grizzly.http.server.Request;
  189.65 +import org.glassfish.grizzly.http.server.Response;
  189.66 +import org.glassfish.grizzly.http.server.ServerConfiguration;
  189.67 +import org.glassfish.grizzly.websockets.WebSocket;
  189.68 +import org.glassfish.grizzly.websockets.WebSocketAddOn;
  189.69 +import org.glassfish.grizzly.websockets.WebSocketApplication;
  189.70 +import org.glassfish.grizzly.websockets.WebSocketEngine;
  189.71 +
  189.72 +/**
  189.73 + *
  189.74 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  189.75 + */
  189.76 +final class DynamicHTTP extends HttpHandler {
  189.77 +    private static final Logger LOG = Logger.getLogger(DynamicHTTP.class.getName());
  189.78 +    private static int resourcesCount;
  189.79 +    private static List<Resource> resources;
  189.80 +    private static ServerConfiguration conf;
  189.81 +    private static HttpServer server;
  189.82 +    
  189.83 +    private DynamicHTTP() {
  189.84 +    }
  189.85 +    
  189.86 +    static URI initServer() throws Exception {
  189.87 +        server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
  189.88 +        final WebSocketAddOn addon = new WebSocketAddOn();
  189.89 +        for (NetworkListener listener : server.getListeners()) {
  189.90 +            listener.registerAddOn(addon);
  189.91 +        }        
  189.92 +        resources = new ArrayList<Resource>();
  189.93 +
  189.94 +        conf = server.getServerConfiguration();
  189.95 +        final DynamicHTTP dh = new DynamicHTTP();
  189.96 +
  189.97 +        conf.addHttpHandler(dh, "/");
  189.98 +        
  189.99 +        server.start();
 189.100 +
 189.101 +        return pageURL("http", server, "/test.html");
 189.102 +    }
 189.103 +    
 189.104 +    @Override
 189.105 +    public void service(Request request, Response response) throws Exception {
 189.106 +        if ("/test.html".equals(request.getRequestURI())) {
 189.107 +            response.setContentType("text/html");
 189.108 +            final InputStream is = DynamicHTTP.class.getResourceAsStream("test.html");
 189.109 +            copyStream(is, response.getOutputStream(), null);
 189.110 +            return;
 189.111 +        }
 189.112 +        if ("/dynamic".equals(request.getRequestURI())) {
 189.113 +            String mimeType = request.getParameter("mimeType");
 189.114 +            List<String> params = new ArrayList<String>();
 189.115 +            boolean webSocket = false;
 189.116 +            for (int i = 0;; i++) {
 189.117 +                String p = request.getParameter("param" + i);
 189.118 +                if (p == null) {
 189.119 +                    break;
 189.120 +                }
 189.121 +                if ("protocol:ws".equals(p)) {
 189.122 +                    webSocket = true;
 189.123 +                    continue;
 189.124 +                }
 189.125 +                params.add(p);
 189.126 +            }
 189.127 +            final String cnt = request.getParameter("content");
 189.128 +            String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
 189.129 +            ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
 189.130 +            URI url;
 189.131 +            final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
 189.132 +            if (webSocket) {
 189.133 +                url = registerWebSocket(res);
 189.134 +            } else {
 189.135 +                url = registerResource(res);
 189.136 +            }
 189.137 +            response.getWriter().write(url.toString());
 189.138 +            response.getWriter().write("\n");
 189.139 +            return;
 189.140 +        }
 189.141 +
 189.142 +        for (Resource r : resources) {
 189.143 +            if (r.httpPath.equals(request.getRequestURI())) {
 189.144 +                response.setContentType(r.httpType);
 189.145 +                r.httpContent.reset();
 189.146 +                String[] params = null;
 189.147 +                if (r.parameters.length != 0) {
 189.148 +                    params = new String[r.parameters.length];
 189.149 +                    for (int i = 0; i < r.parameters.length; i++) {
 189.150 +                        params[i] = request.getParameter(r.parameters[i]);
 189.151 +                        if (params[i] == null) {
 189.152 +                            if ("http.method".equals(r.parameters[i])) {
 189.153 +                                params[i] = request.getMethod().toString();
 189.154 +                            } else if ("http.requestBody".equals(r.parameters[i])) {
 189.155 +                                Reader rdr = request.getReader();
 189.156 +                                StringBuilder sb = new StringBuilder();
 189.157 +                                for (;;) {
 189.158 +                                    int ch = rdr.read();
 189.159 +                                    if (ch == -1) {
 189.160 +                                        break;
 189.161 +                                    }
 189.162 +                                    sb.append((char) ch);
 189.163 +                                }
 189.164 +                                params[i] = sb.toString();
 189.165 +                            }
 189.166 +                        }
 189.167 +                        if (params[i] == null) {
 189.168 +                            params[i] = "null";
 189.169 +                        }
 189.170 +                    }
 189.171 +                }
 189.172 +
 189.173 +                copyStream(r.httpContent, response.getOutputStream(), null, params);
 189.174 +            }
 189.175 +        }
 189.176 +    }
 189.177 +    
 189.178 +    private URI registerWebSocket(Resource r) {
 189.179 +        WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
 189.180 +        return pageURL("ws", server, r.httpPath);
 189.181 +    }
 189.182 +
 189.183 +    private URI registerResource(Resource r) {
 189.184 +        if (!resources.contains(r)) {
 189.185 +            resources.add(r);
 189.186 +            conf.addHttpHandler(this, r.httpPath);
 189.187 +        }
 189.188 +        return pageURL("http", server, r.httpPath);
 189.189 +    }
 189.190 +    
 189.191 +    private static URI pageURL(String proto, HttpServer server, final String page) {
 189.192 +        NetworkListener listener = server.getListeners().iterator().next();
 189.193 +        int port = listener.getPort();
 189.194 +        try {
 189.195 +            return new URI(proto + "://localhost:" + port + page);
 189.196 +        } catch (URISyntaxException ex) {
 189.197 +            throw new IllegalStateException(ex);
 189.198 +        }
 189.199 +    }
 189.200 +    
 189.201 +    static final class Resource {
 189.202 +
 189.203 +        final InputStream httpContent;
 189.204 +        final String httpType;
 189.205 +        final String httpPath;
 189.206 +        final String[] parameters;
 189.207 +
 189.208 +        Resource(InputStream httpContent, String httpType, String httpPath,
 189.209 +            String[] parameters) {
 189.210 +            httpContent.mark(Integer.MAX_VALUE);
 189.211 +            this.httpContent = httpContent;
 189.212 +            this.httpType = httpType;
 189.213 +            this.httpPath = httpPath;
 189.214 +            this.parameters = parameters;
 189.215 +        }
 189.216 +    }
 189.217 +
 189.218 +    static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
 189.219 +        for (;;) {
 189.220 +            int ch = is.read();
 189.221 +            if (ch == -1) {
 189.222 +                break;
 189.223 +            }
 189.224 +            if (ch == '$' && params.length > 0) {
 189.225 +                int cnt = is.read() - '0';
 189.226 +                if (baseURL != null && cnt == 'U' - '0') {
 189.227 +                    os.write(baseURL.getBytes("UTF-8"));
 189.228 +                } else {
 189.229 +                    if (cnt >= 0 && cnt < params.length) {
 189.230 +                        os.write(params[cnt].getBytes("UTF-8"));
 189.231 +                    } else {
 189.232 +                        os.write('$');
 189.233 +                        os.write(cnt + '0');
 189.234 +                    }
 189.235 +                }
 189.236 +            } else {
 189.237 +                os.write(ch);
 189.238 +            }
 189.239 +        }
 189.240 +    }
 189.241 +    
 189.242 +    private static class WS extends WebSocketApplication {
 189.243 +        private final Resource r;
 189.244 +
 189.245 +        private WS(Resource r) {
 189.246 +            this.r = r;
 189.247 +        }
 189.248 +
 189.249 +        @Override
 189.250 +        public void onMessage(WebSocket socket, String text) {
 189.251 +            try {
 189.252 +                r.httpContent.reset();
 189.253 +                ByteArrayOutputStream out = new ByteArrayOutputStream();
 189.254 +                copyStream(r.httpContent, out, null, text);
 189.255 +                String s = new String(out.toByteArray(), "UTF-8");
 189.256 +                socket.send(s);
 189.257 +            } catch (IOException ex) {
 189.258 +                LOG.log(Level.WARNING, "Error processing message " + text, ex);
 189.259 +            }
 189.260 +        }
 189.261 +    }
 189.262 +}
   190.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   190.2 +++ b/ko-fx/src/test/java/org/netbeans/html/kofx/KOFx.java	Mon Dec 16 17:16:40 2013 +0100
   190.3 @@ -0,0 +1,118 @@
   190.4 +/**
   190.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   190.6 + *
   190.7 + * Copyright 1997-2010 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.lang.reflect.InvocationTargetException;
  190.50 +import java.lang.reflect.Method;
  190.51 +import javafx.application.Platform;
  190.52 +import org.apidesign.html.boot.spi.Fn;
  190.53 +import org.testng.ITest;
  190.54 +import org.testng.annotations.Test;
  190.55 +
  190.56 +/**
  190.57 + *
  190.58 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  190.59 + */
  190.60 +public final class KOFx implements ITest, Runnable {
  190.61 +    private final Fn.Presenter p;
  190.62 +    private final Method m;
  190.63 +    private Object result;
  190.64 +    private Object inst;
  190.65 +    private int count;
  190.66 +
  190.67 +    KOFx(Fn.Presenter p, Method m) {
  190.68 +        this.p = p;
  190.69 +        this.m = m;
  190.70 +    }
  190.71 +
  190.72 +    @Override
  190.73 +    public String getTestName() {
  190.74 +        return m.getName();
  190.75 +    }
  190.76 +
  190.77 +    @Test
  190.78 +    public synchronized void executeTest() throws Exception {
  190.79 +        if (result == null) {
  190.80 +            Platform.runLater(this);
  190.81 +            wait();
  190.82 +        }
  190.83 +        if (result instanceof Exception) {
  190.84 +            throw (Exception)result;
  190.85 +        }
  190.86 +        if (result instanceof Error) {
  190.87 +            throw (Error)result;
  190.88 +        }
  190.89 +    }
  190.90 +
  190.91 +    @Override
  190.92 +    public synchronized void run() {
  190.93 +        boolean notify = true;
  190.94 +        try (Closeable a = Fn.activate(p)) {
  190.95 +            if (inst == null) {
  190.96 +                inst = m.getDeclaringClass().newInstance();
  190.97 +            }
  190.98 +            result = m.invoke(inst);
  190.99 +            if (result == null) {
 190.100 +                result = this;
 190.101 +            }
 190.102 +        } catch (InvocationTargetException ex) {
 190.103 +            Throwable r = ex.getTargetException();
 190.104 +            if (r instanceof InterruptedException) {
 190.105 +                if (count++ < 10000) {
 190.106 +                    notify = false;
 190.107 +                    Platform.runLater(this);
 190.108 +                    return;
 190.109 +                }
 190.110 +            }
 190.111 +            result = r;
 190.112 +        } catch (Exception ex) {
 190.113 +            result = ex;
 190.114 +        } finally {
 190.115 +            if (notify) {
 190.116 +                notifyAll();
 190.117 +            }
 190.118 +        }
 190.119 +    }
 190.120 +    
 190.121 +}
   191.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   191.2 +++ b/ko-fx/src/test/java/org/netbeans/html/kofx/KnockoutFXTest.java	Mon Dec 16 17:16:40 2013 +0100
   191.3 @@ -0,0 +1,229 @@
   191.4 +/**
   191.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   191.6 + *
   191.7 + * Copyright 1997-2010 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 java.io.BufferedReader;
  191.49 +import java.io.IOException;
  191.50 +import java.io.InputStreamReader;
  191.51 +import java.lang.annotation.Annotation;
  191.52 +import java.lang.reflect.Method;
  191.53 +import java.net.URI;
  191.54 +import java.net.URISyntaxException;
  191.55 +import java.net.URL;
  191.56 +import java.net.URLConnection;
  191.57 +import java.util.ArrayList;
  191.58 +import java.util.List;
  191.59 +import java.util.Map;
  191.60 +import java.util.concurrent.Executors;
  191.61 +import net.java.html.BrwsrCtx;
  191.62 +import net.java.html.boot.BrowserBuilder;
  191.63 +import net.java.html.js.JavaScriptBody;
  191.64 +import org.netbeans.html.boot.impl.FnContext;
  191.65 +import org.apidesign.html.boot.spi.Fn;
  191.66 +import org.apidesign.html.context.spi.Contexts;
  191.67 +import org.apidesign.html.json.spi.Technology;
  191.68 +import org.apidesign.html.json.spi.Transfer;
  191.69 +import org.apidesign.html.json.spi.WSTransfer;
  191.70 +import org.apidesign.html.json.tck.KOTest;
  191.71 +import org.apidesign.html.json.tck.KnockoutTCK;
  191.72 +import org.json.JSONException;
  191.73 +import org.json.JSONObject;
  191.74 +import org.openide.util.lookup.ServiceProvider;
  191.75 +import org.testng.annotations.Factory;
  191.76 +import static org.testng.Assert.*;
  191.77 +
  191.78 +/**
  191.79 + *
  191.80 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  191.81 + */
  191.82 +@ServiceProvider(service = KnockoutTCK.class)
  191.83 +public final class KnockoutFXTest extends KnockoutTCK {
  191.84 +    private static Class<?> browserClass;
  191.85 +    private static Fn.Presenter browserContext;
  191.86 +    
  191.87 +    public KnockoutFXTest() {
  191.88 +    }
  191.89 +    
  191.90 +    @Factory public static Object[] compatibilityTests() throws Exception {
  191.91 +        Class[] arr = testClasses();
  191.92 +        for (int i = 0; i < arr.length; i++) {
  191.93 +            assertEquals(
  191.94 +                arr[i].getClassLoader(),
  191.95 +                KnockoutFXTest.class.getClassLoader(),
  191.96 +                "All classes loaded by the same classloader"
  191.97 +            );
  191.98 +        }
  191.99 +        
 191.100 +        URI uri = DynamicHTTP.initServer();
 191.101 +    
 191.102 +        final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(KnockoutFXTest.class).
 191.103 +            loadPage(uri.toString()).
 191.104 +            invoke("initialized");
 191.105 +        
 191.106 +        Executors.newSingleThreadExecutor().submit(new Runnable() {
 191.107 +            @Override
 191.108 +            public void run() {
 191.109 +                bb.showAndWait();
 191.110 +            }
 191.111 +        });
 191.112 +        
 191.113 +        ClassLoader l = getClassLoader();
 191.114 +        List<Object> res = new ArrayList<Object>();
 191.115 +        for (int i = 0; i < arr.length; i++) {
 191.116 +            Class<?> c = Class.forName(arr[i].getName(), true, l);
 191.117 +            seekKOTests(c, res);
 191.118 +        }
 191.119 +        Class<?> c = Class.forName(LessCallbacksCheck.class.getName(), true, l);
 191.120 +        seekKOTests(c, res);
 191.121 +        return res.toArray();
 191.122 +    }
 191.123 +
 191.124 +    private static void seekKOTests(Class<?> c, List<Object> res) throws SecurityException, ClassNotFoundException {
 191.125 +        Class<? extends Annotation> koTest =
 191.126 +            c.getClassLoader().loadClass(KOTest.class.getName()).
 191.127 +            asSubclass(Annotation.class);
 191.128 +        for (Method m : c.getMethods()) {
 191.129 +            if (m.getAnnotation(koTest) != null) {
 191.130 +                res.add(new KOFx(browserContext, m));
 191.131 +            }
 191.132 +        }
 191.133 +    }
 191.134 +
 191.135 +    static synchronized ClassLoader getClassLoader() throws InterruptedException {
 191.136 +        while (browserClass == null) {
 191.137 +            KnockoutFXTest.class.wait();
 191.138 +        }
 191.139 +        return browserClass.getClassLoader();
 191.140 +    }
 191.141 +    
 191.142 +    public static synchronized void initialized(Class<?> browserCls) throws Exception {
 191.143 +        browserClass = browserCls;
 191.144 +        browserContext = FnContext.currentPresenter();
 191.145 +        KnockoutFXTest.class.notifyAll();
 191.146 +    }
 191.147 +    
 191.148 +    public static void initialized() throws Exception {
 191.149 +        Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(KnockoutFXTest.class.getName());
 191.150 +        Method m = classpathClass.getMethod("initialized", Class.class);
 191.151 +        m.invoke(null, KnockoutFXTest.class);
 191.152 +        browserContext = FnContext.currentPresenter();
 191.153 +    }
 191.154 +    
 191.155 +    @Override
 191.156 +    public BrwsrCtx createContext() {
 191.157 +        FXContext fx = new FXContext(browserContext);
 191.158 +        Contexts.Builder cb = Contexts.newBuilder().
 191.159 +            register(Technology.class, fx, 10).
 191.160 +            register(Transfer.class, fx, 10);
 191.161 +        if (fx.areWebSocketsSupported()) {
 191.162 +            cb.register(WSTransfer.class, fx, 10);
 191.163 +        }
 191.164 +        return cb.build();
 191.165 +    }
 191.166 +
 191.167 +    @Override
 191.168 +    public Object createJSON(Map<String, Object> values) {
 191.169 +        JSONObject json = new JSONObject();
 191.170 +        for (Map.Entry<String, Object> entry : values.entrySet()) {
 191.171 +            try {
 191.172 +                json.put(entry.getKey(), entry.getValue());
 191.173 +            } catch (JSONException ex) {
 191.174 +                throw new IllegalStateException(ex);
 191.175 +            }
 191.176 +        }
 191.177 +        return json;
 191.178 +    }
 191.179 +
 191.180 +    @Override
 191.181 +    @JavaScriptBody(args = { "s", "args" }, body = ""
 191.182 +        + "var f = new Function(s); "
 191.183 +        + "return f.apply(null, args);"
 191.184 +    )
 191.185 +    public native Object executeScript(String script, Object[] arguments);
 191.186 +
 191.187 +    @JavaScriptBody(args = {  }, body = 
 191.188 +          "var h;"
 191.189 +        + "if (!!window && !!window.location && !!window.location.href)\n"
 191.190 +        + "  h = window.location.href;\n"
 191.191 +        + "else "
 191.192 +        + "  h = null;"
 191.193 +        + "return h;\n"
 191.194 +    )
 191.195 +    private static native String findBaseURL();
 191.196 +    
 191.197 +    @Override
 191.198 +    public URI prepareURL(String content, String mimeType, String[] parameters) {
 191.199 +        try {
 191.200 +            final URL baseURL = new URL(findBaseURL());
 191.201 +            StringBuilder sb = new StringBuilder();
 191.202 +            sb.append("/dynamic?mimeType=").append(mimeType);
 191.203 +            for (int i = 0; i < parameters.length; i++) {
 191.204 +                sb.append("&param" + i).append("=").append(parameters[i]);
 191.205 +            }
 191.206 +            String mangle = content.replace("\n", "%0a")
 191.207 +                .replace("\"", "\\\"").replace(" ", "%20");
 191.208 +            sb.append("&content=").append(mangle);
 191.209 +
 191.210 +            URL query = new URL(baseURL, sb.toString());
 191.211 +            URLConnection c = query.openConnection();
 191.212 +            BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
 191.213 +            URI connectTo = new URI(br.readLine());
 191.214 +            return connectTo;
 191.215 +        } catch (IOException ex) {
 191.216 +            throw new IllegalStateException(ex);
 191.217 +        } catch (URISyntaxException ex) {
 191.218 +            throw new IllegalStateException(ex);
 191.219 +        }
 191.220 +    }
 191.221 +
 191.222 +    @Override
 191.223 +    public boolean canFailWebSocketTest() {
 191.224 +        try {
 191.225 +            Class.forName("java.util.function.Function");
 191.226 +            return false;
 191.227 +        } catch (ClassNotFoundException ex) {
 191.228 +            // running on JDK7, FX WebView WebSocket impl does not work
 191.229 +            return true;
 191.230 +        }
 191.231 +    }
 191.232 +}
   192.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   192.2 +++ b/ko-fx/src/test/java/org/netbeans/html/kofx/LessCallbacksCheck.java	Mon Dec 16 17:16:40 2013 +0100
   192.3 @@ -0,0 +1,82 @@
   192.4 +/**
   192.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   192.6 + *
   192.7 + * Copyright 1997-2010 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.PrintWriter;
  192.49 +import java.io.StringWriter;
  192.50 +import net.java.html.json.ComputedProperty;
  192.51 +import net.java.html.json.Model;
  192.52 +import net.java.html.json.Property;
  192.53 +import org.apidesign.html.json.tck.KOTest;
  192.54 +
  192.55 +/**
  192.56 + *
  192.57 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  192.58 + */
  192.59 +@Model(className = "LessCalls", properties = {
  192.60 +    @Property(name = "value", type = int.class)
  192.61 +})
  192.62 +public class LessCallbacksCheck {
  192.63 +    private static StringWriter sw;
  192.64 +    
  192.65 +    @ComputedProperty static int plusOne(int value) {
  192.66 +        if (sw == null) {
  192.67 +            sw = new StringWriter();
  192.68 +        }
  192.69 +        new Exception("Who calls me?").printStackTrace(
  192.70 +            new PrintWriter(sw)
  192.71 +        );
  192.72 +        return value + 1;
  192.73 +    }
  192.74 +    
  192.75 +    @KOTest public void dontCallForInitialValueBackToJavaVM() {
  192.76 +        LessCalls m = new LessCalls(10).applyBindings();
  192.77 +        assert m.getPlusOne() == 11 : "Expecting 11: " + m.getPlusOne();
  192.78 +        
  192.79 +        assert sw != null : "StringWriter should be initialized: " + sw;
  192.80 +        
  192.81 +        if (sw.toString().contains("$JsCallbacks$")) {
  192.82 +            assert false : "Don't call for initial value via JsCallbacks:\n" + sw;
  192.83 +        }
  192.84 +    }
  192.85 +}
   193.1 --- a/ko-fx/src/test/resources/org/apidesign/html/kofx/test.html	Mon Dec 16 17:16:02 2013 +0100
   193.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   193.3 @@ -1,34 +0,0 @@
   193.4 -<!--
   193.5 -
   193.6 -    HTML via Java(tm) Language Bindings
   193.7 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   193.8 -
   193.9 -    This program is free software: you can redistribute it and/or modify
  193.10 -    it under the terms of the GNU General Public License as published by
  193.11 -    the Free Software Foundation, version 2 of the License.
  193.12 -
  193.13 -    This program is distributed in the hope that it will be useful,
  193.14 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
  193.15 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  193.16 -    GNU General Public License for more details. apidesign.org
  193.17 -    designates this particular file as subject to the
  193.18 -    "Classpath" exception as provided by apidesign.org
  193.19 -    in the License file that accompanied this code.
  193.20 -
  193.21 -    You should have received a copy of the GNU General Public License
  193.22 -    along with this program. Look for COPYING file in the top folder.
  193.23 -    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  193.24 -
  193.25 --->
  193.26 -<!DOCTYPE html>
  193.27 -<html>
  193.28 -    <head>
  193.29 -        <title>Knockout.fx Execution Harness</title>
  193.30 -        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  193.31 -        <meta name="viewport" content="width=device-width">
  193.32 -    </head>
  193.33 -    <body>
  193.34 -        <h1>Knockout.fx Execution Harness</h1>
  193.35 -    </body>
  193.36 -    <script></script>
  193.37 -</html>
   194.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   194.2 +++ b/ko-fx/src/test/resources/org/netbeans/html/kofx/test.html	Mon Dec 16 17:16:40 2013 +0100
   194.3 @@ -0,0 +1,56 @@
   194.4 +<!--
   194.5 +
   194.6 +    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   194.7 +
   194.8 +    Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   194.9 +
  194.10 +    Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  194.11 +    Other names may be trademarks of their respective owners.
  194.12 +
  194.13 +    The contents of this file are subject to the terms of either the GNU
  194.14 +    General Public License Version 2 only ("GPL") or the Common
  194.15 +    Development and Distribution License("CDDL") (collectively, the
  194.16 +    "License"). You may not use this file except in compliance with the
  194.17 +    License. You can obtain a copy of the License at
  194.18 +    http://www.netbeans.org/cddl-gplv2.html
  194.19 +    or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  194.20 +    specific language governing permissions and limitations under the
  194.21 +    License.  When distributing the software, include this License Header
  194.22 +    Notice in each file and include the License file at
  194.23 +    nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  194.24 +    particular file as subject to the "Classpath" exception as provided
  194.25 +    by Oracle in the GPL Version 2 section of the License file that
  194.26 +    accompanied this code. If applicable, add the following below the
  194.27 +    License Header, with the fields enclosed by brackets [] replaced by
  194.28 +    your own identifying information:
  194.29 +    "Portions Copyrighted [year] [name of copyright owner]"
  194.30 +
  194.31 +    Contributor(s):
  194.32 +
  194.33 +    The Original Software is NetBeans. The Initial Developer of the Original
  194.34 +    Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  194.35 +
  194.36 +    If you wish your version of this file to be governed by only the CDDL
  194.37 +    or only the GPL Version 2, indicate your decision by adding
  194.38 +    "[Contributor] elects to include this software in this distribution
  194.39 +    under the [CDDL or GPL Version 2] license." If you do not indicate a
  194.40 +    single choice of license, a recipient has the option to distribute
  194.41 +    your version of this file under either the CDDL, the GPL Version 2 or
  194.42 +    to extend the choice of license to its licensees as provided above.
  194.43 +    However, if you add GPL Version 2 code and therefore, elected the GPL
  194.44 +    Version 2 license, then the option applies only if the new code is
  194.45 +    made subject to such option by the copyright holder.
  194.46 +
  194.47 +-->
  194.48 +<!DOCTYPE html>
  194.49 +<html>
  194.50 +    <head>
  194.51 +        <title>Knockout.fx Execution Harness</title>
  194.52 +        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  194.53 +        <meta name="viewport" content="width=device-width">
  194.54 +    </head>
  194.55 +    <body>
  194.56 +        <h1>Knockout.fx Execution Harness</h1>
  194.57 +    </body>
  194.58 +    <script></script>
  194.59 +</html>
   195.1 --- a/ko-ws-tyrus/pom.xml	Mon Dec 16 17:16:02 2013 +0100
   195.2 +++ b/ko-ws-tyrus/pom.xml	Mon Dec 16 17:16:40 2013 +0100
   195.3 @@ -2,11 +2,11 @@
   195.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">
   195.5    <modelVersion>4.0.0</modelVersion>
   195.6    <parent>
   195.7 -    <groupId>org.apidesign</groupId>
   195.8 -    <artifactId>html</artifactId>
   195.9 +    <groupId>org.netbeans.html</groupId>
  195.10 +    <artifactId>pom</artifactId>
  195.11      <version>0.7-SNAPSHOT</version>
  195.12    </parent>
  195.13 -  <groupId>org.apidesign.html</groupId>
  195.14 +  <groupId>org.netbeans.html</groupId>
  195.15    <artifactId>ko-ws-tyrus</artifactId>
  195.16    <version>0.7-SNAPSHOT</version>
  195.17    <packaging>bundle</packaging>
  195.18 @@ -38,6 +38,7 @@
  195.19      </build>
  195.20      <properties>
  195.21      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  195.22 +    <bundleSymbolicName>org.netbeans.html.ko-ws-tyrus</bundleSymbolicName>
  195.23    </properties>
  195.24    <dependencies>
  195.25      <!-- compile only deps -->
  195.26 @@ -126,7 +127,7 @@
  195.27      </dependency>
  195.28      <dependency>
  195.29          <groupId>${project.groupId}</groupId>
  195.30 -        <artifactId>boot-fx</artifactId>
  195.31 +        <artifactId>net.java.html.boot.fx</artifactId>
  195.32          <version>${project.version}</version>
  195.33          <scope>test</scope>
  195.34      </dependency>
   196.1 --- a/ko-ws-tyrus/src/main/java/org/apidesign/html/wstyrus/TyrusContext.java	Mon Dec 16 17:16:02 2013 +0100
   196.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   196.3 @@ -1,168 +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.wstyrus;
  196.25 -
  196.26 -import java.io.IOException;
  196.27 -import java.net.URI;
  196.28 -import java.net.URISyntaxException;
  196.29 -import java.util.Iterator;
  196.30 -import javax.websocket.ClientEndpoint;
  196.31 -import javax.websocket.ContainerProvider;
  196.32 -import javax.websocket.DeploymentException;
  196.33 -import javax.websocket.OnClose;
  196.34 -import javax.websocket.OnError;
  196.35 -import javax.websocket.OnMessage;
  196.36 -import javax.websocket.OnOpen;
  196.37 -import javax.websocket.Session;
  196.38 -import javax.websocket.WebSocketContainer;
  196.39 -import net.java.html.json.OnReceive;
  196.40 -import org.apidesign.html.context.spi.Contexts;
  196.41 -import org.apidesign.html.json.spi.JSONCall;
  196.42 -import org.apidesign.html.json.spi.WSTransfer;
  196.43 -import org.apidesign.html.wstyrus.TyrusContext.Comm;
  196.44 -import org.json.JSONArray;
  196.45 -import org.json.JSONException;
  196.46 -import org.json.JSONObject;
  196.47 -import org.json.JSONTokener;
  196.48 -import org.openide.util.lookup.ServiceProvider;
  196.49 -
  196.50 -/** This is an implementation module that provides support for
  196.51 - * WebSocket protocol for {@link OnReceive} communication end point for
  196.52 - * JDK7.
  196.53 - * <p>
  196.54 - * Don't deal with this module directly, rather use the 
  196.55 - * {@link OnReceive @OnReceive(url="ws://...", ...)} API to establish your
  196.56 - * WebSocket connection.
  196.57 - * <p>
  196.58 - * There is no need to include this module in your application if you are
  196.59 - * running on JDK8. JDK8 WebView provides its own implementation of the
  196.60 - * WebSocket API based on WebSocket object inside a browser. This is included
  196.61 - * in the <code>org.apidesign.html:ko-fx:0.5</code> module.
  196.62 - *
  196.63 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  196.64 - */
  196.65 -@ServiceProvider(service = Contexts.Provider.class)
  196.66 -public final class TyrusContext implements Contexts.Provider, WSTransfer<Comm> {
  196.67 -    @Override
  196.68 -    public void fillContext(Contexts.Builder context, Class<?> requestor) {
  196.69 -        // default WebSocket transfer implementation is registered
  196.70 -        // in ko-fx module with 100, provide this one as a fallback only
  196.71 -        context.register(WSTransfer.class, this, 1000);
  196.72 -    }
  196.73 -
  196.74 -    @Override
  196.75 -    public Comm open(String url, JSONCall callback) {
  196.76 -        try {
  196.77 -            return new Comm(new URI(url), callback);
  196.78 -        } catch (URISyntaxException ex) {
  196.79 -            throw new IllegalStateException(ex);
  196.80 -        }
  196.81 -    }
  196.82 -
  196.83 -    @Override
  196.84 -    public void send(Comm socket, JSONCall data) {
  196.85 -        socket.session.getAsyncRemote().sendText(data.getMessage());
  196.86 -    }
  196.87 -
  196.88 -    @Override
  196.89 -    public void close(Comm socket) {
  196.90 -        try {
  196.91 -            final Session s = socket.session;
  196.92 -            if (s != null) {
  196.93 -                s.close();
  196.94 -            }
  196.95 -        } catch (IOException ex) {
  196.96 -            socket.callback.notifyError(ex);
  196.97 -        }
  196.98 -    }
  196.99 -    
 196.100 -    /** Implementation class in an implementation. Represents a {@link ClientEndpoint} of the
 196.101 -     * WebSocket channel. You are unlikely to get on hold of it.
 196.102 -     */
 196.103 -    @ClientEndpoint
 196.104 -    public static final class Comm {
 196.105 -        private final JSONCall callback;
 196.106 -        private Session session;
 196.107 -
 196.108 -        Comm(final URI url, JSONCall callback) {
 196.109 -            this.callback = callback;
 196.110 -            try {
 196.111 -                final WebSocketContainer c = ContainerProvider.getWebSocketContainer();
 196.112 -                c.connectToServer(Comm.this, url);
 196.113 -            } catch (DeploymentException | IOException ex) {
 196.114 -                wasAnError(ex);
 196.115 -            }
 196.116 -        }
 196.117 -
 196.118 -        @OnOpen
 196.119 -        public synchronized void open(Session s) {
 196.120 -            this.session = s;
 196.121 -            callback.notifySuccess(null);
 196.122 -        }
 196.123 -
 196.124 -        @OnClose
 196.125 -        public void close() {
 196.126 -            this.session = null;
 196.127 -            callback.notifyError(null);
 196.128 -        }
 196.129 -
 196.130 -        @OnMessage
 196.131 -        public void message(final String orig, Session s) {
 196.132 -            Object json;
 196.133 -            String data = orig.trim();
 196.134 -            try {
 196.135 -                JSONTokener tok = new JSONTokener(data);
 196.136 -                Object obj = data.startsWith("[") ? new JSONArray(tok) : new JSONObject(tok);
 196.137 -                json = convertToArray(obj);
 196.138 -            } catch (JSONException ex) {
 196.139 -                json = data;
 196.140 -            }
 196.141 -            callback.notifySuccess(json);
 196.142 -        }
 196.143 -
 196.144 -        @OnError
 196.145 -        public void wasAnError(Throwable t) {
 196.146 -            callback.notifyError(t);
 196.147 -        }
 196.148 -
 196.149 -        static Object convertToArray(Object o) throws JSONException {
 196.150 -            if (o instanceof JSONArray) {
 196.151 -                JSONArray ja = (JSONArray) o;
 196.152 -                Object[] arr = new Object[ja.length()];
 196.153 -                for (int i = 0; i < arr.length; i++) {
 196.154 -                    arr[i] = convertToArray(ja.get(i));
 196.155 -                }
 196.156 -                return arr;
 196.157 -            } else if (o instanceof JSONObject) {
 196.158 -                JSONObject obj = (JSONObject) o;
 196.159 -                Iterator it = obj.keys();
 196.160 -                while (it.hasNext()) {
 196.161 -                    String key = (String) it.next();
 196.162 -                    obj.put(key, convertToArray(obj.get(key)));
 196.163 -                }
 196.164 -                return obj;
 196.165 -            } else {
 196.166 -                return o;
 196.167 -            }
 196.168 -        }
 196.169 -        
 196.170 -    } // end of Comm
 196.171 -}
   197.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   197.2 +++ b/ko-ws-tyrus/src/main/java/org/netbeans/html/wstyrus/TyrusContext.java	Mon Dec 16 17:16:40 2013 +0100
   197.3 @@ -0,0 +1,190 @@
   197.4 +/**
   197.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   197.6 + *
   197.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   197.8 + *
   197.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  197.10 + * Other names may be trademarks of their respective owners.
  197.11 + *
  197.12 + * The contents of this file are subject to the terms of either the GNU
  197.13 + * General Public License Version 2 only ("GPL") or the Common
  197.14 + * Development and Distribution License("CDDL") (collectively, the
  197.15 + * "License"). You may not use this file except in compliance with the
  197.16 + * License. You can obtain a copy of the License at
  197.17 + * http://www.netbeans.org/cddl-gplv2.html
  197.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  197.19 + * specific language governing permissions and limitations under the
  197.20 + * License.  When distributing the software, include this License Header
  197.21 + * Notice in each file and include the License file at
  197.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  197.23 + * particular file as subject to the "Classpath" exception as provided
  197.24 + * by Oracle in the GPL Version 2 section of the License file that
  197.25 + * accompanied this code. If applicable, add the following below the
  197.26 + * License Header, with the fields enclosed by brackets [] replaced by
  197.27 + * your own identifying information:
  197.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  197.29 + *
  197.30 + * Contributor(s):
  197.31 + *
  197.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  197.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  197.34 + *
  197.35 + * If you wish your version of this file to be governed by only the CDDL
  197.36 + * or only the GPL Version 2, indicate your decision by adding
  197.37 + * "[Contributor] elects to include this software in this distribution
  197.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  197.39 + * single choice of license, a recipient has the option to distribute
  197.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  197.41 + * to extend the choice of license to its licensees as provided above.
  197.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  197.43 + * Version 2 license, then the option applies only if the new code is
  197.44 + * made subject to such option by the copyright holder.
  197.45 + */
  197.46 +package org.netbeans.html.wstyrus;
  197.47 +
  197.48 +import java.io.IOException;
  197.49 +import java.net.URI;
  197.50 +import java.net.URISyntaxException;
  197.51 +import java.util.Iterator;
  197.52 +import javax.websocket.ClientEndpoint;
  197.53 +import javax.websocket.ContainerProvider;
  197.54 +import javax.websocket.DeploymentException;
  197.55 +import javax.websocket.OnClose;
  197.56 +import javax.websocket.OnError;
  197.57 +import javax.websocket.OnMessage;
  197.58 +import javax.websocket.OnOpen;
  197.59 +import javax.websocket.Session;
  197.60 +import javax.websocket.WebSocketContainer;
  197.61 +import net.java.html.json.OnReceive;
  197.62 +import org.apidesign.html.context.spi.Contexts;
  197.63 +import org.apidesign.html.json.spi.JSONCall;
  197.64 +import org.apidesign.html.json.spi.WSTransfer;
  197.65 +import org.netbeans.html.wstyrus.TyrusContext.Comm;
  197.66 +import org.json.JSONArray;
  197.67 +import org.json.JSONException;
  197.68 +import org.json.JSONObject;
  197.69 +import org.json.JSONTokener;
  197.70 +import org.openide.util.lookup.ServiceProvider;
  197.71 +
  197.72 +/** This is an implementation module that provides support for
  197.73 + * WebSocket protocol for {@link OnReceive} communication end point for
  197.74 + * JDK7.
  197.75 + * <p>
  197.76 + * Don't deal with this module directly, rather use the 
  197.77 + * {@link OnReceive @OnReceive(url="ws://...", ...)} API to establish your
  197.78 + * WebSocket connection.
  197.79 + * <p>
  197.80 + * There is no need to include this module in your application if you are
  197.81 + * running on JDK8. JDK8 WebView provides its own implementation of the
  197.82 + * WebSocket API based on WebSocket object inside a browser. This is included
  197.83 + * in the <code>org.apidesign.html:ko-fx:0.5</code> module.
  197.84 + *
  197.85 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  197.86 + */
  197.87 +@ServiceProvider(service = Contexts.Provider.class)
  197.88 +public final class TyrusContext implements Contexts.Provider, WSTransfer<Comm> {
  197.89 +    @Override
  197.90 +    public void fillContext(Contexts.Builder context, Class<?> requestor) {
  197.91 +        // default WebSocket transfer implementation is registered
  197.92 +        // in ko-fx module with 100, provide this one as a fallback only
  197.93 +        context.register(WSTransfer.class, this, 1000);
  197.94 +    }
  197.95 +
  197.96 +    @Override
  197.97 +    public Comm open(String url, JSONCall callback) {
  197.98 +        try {
  197.99 +            return new Comm(new URI(url), callback);
 197.100 +        } catch (URISyntaxException ex) {
 197.101 +            throw new IllegalStateException(ex);
 197.102 +        }
 197.103 +    }
 197.104 +
 197.105 +    @Override
 197.106 +    public void send(Comm socket, JSONCall data) {
 197.107 +        socket.session.getAsyncRemote().sendText(data.getMessage());
 197.108 +    }
 197.109 +
 197.110 +    @Override
 197.111 +    public void close(Comm socket) {
 197.112 +        try {
 197.113 +            final Session s = socket.session;
 197.114 +            if (s != null) {
 197.115 +                s.close();
 197.116 +            }
 197.117 +        } catch (IOException ex) {
 197.118 +            socket.callback.notifyError(ex);
 197.119 +        }
 197.120 +    }
 197.121 +    
 197.122 +    /** Implementation class in an implementation. Represents a {@link ClientEndpoint} of the
 197.123 +     * WebSocket channel. You are unlikely to get on hold of it.
 197.124 +     */
 197.125 +    @ClientEndpoint
 197.126 +    public static final class Comm {
 197.127 +        private final JSONCall callback;
 197.128 +        private Session session;
 197.129 +
 197.130 +        Comm(final URI url, JSONCall callback) {
 197.131 +            this.callback = callback;
 197.132 +            try {
 197.133 +                final WebSocketContainer c = ContainerProvider.getWebSocketContainer();
 197.134 +                c.connectToServer(Comm.this, url);
 197.135 +            } catch (DeploymentException | IOException ex) {
 197.136 +                wasAnError(ex);
 197.137 +            }
 197.138 +        }
 197.139 +
 197.140 +        @OnOpen
 197.141 +        public synchronized void open(Session s) {
 197.142 +            this.session = s;
 197.143 +            callback.notifySuccess(null);
 197.144 +        }
 197.145 +
 197.146 +        @OnClose
 197.147 +        public void close() {
 197.148 +            this.session = null;
 197.149 +            callback.notifyError(null);
 197.150 +        }
 197.151 +
 197.152 +        @OnMessage
 197.153 +        public void message(final String orig, Session s) {
 197.154 +            Object json;
 197.155 +            String data = orig.trim();
 197.156 +            try {
 197.157 +                JSONTokener tok = new JSONTokener(data);
 197.158 +                Object obj = data.startsWith("[") ? new JSONArray(tok) : new JSONObject(tok);
 197.159 +                json = convertToArray(obj);
 197.160 +            } catch (JSONException ex) {
 197.161 +                json = data;
 197.162 +            }
 197.163 +            callback.notifySuccess(json);
 197.164 +        }
 197.165 +
 197.166 +        @OnError
 197.167 +        public void wasAnError(Throwable t) {
 197.168 +            callback.notifyError(t);
 197.169 +        }
 197.170 +
 197.171 +        static Object convertToArray(Object o) throws JSONException {
 197.172 +            if (o instanceof JSONArray) {
 197.173 +                JSONArray ja = (JSONArray) o;
 197.174 +                Object[] arr = new Object[ja.length()];
 197.175 +                for (int i = 0; i < arr.length; i++) {
 197.176 +                    arr[i] = convertToArray(ja.get(i));
 197.177 +                }
 197.178 +                return arr;
 197.179 +            } else if (o instanceof JSONObject) {
 197.180 +                JSONObject obj = (JSONObject) o;
 197.181 +                Iterator it = obj.keys();
 197.182 +                while (it.hasNext()) {
 197.183 +                    String key = (String) it.next();
 197.184 +                    obj.put(key, convertToArray(obj.get(key)));
 197.185 +                }
 197.186 +                return obj;
 197.187 +            } else {
 197.188 +                return o;
 197.189 +            }
 197.190 +        }
 197.191 +        
 197.192 +    } // end of Comm
 197.193 +}
   198.1 --- a/ko-ws-tyrus/src/test/java/org/apidesign/html/wstyrus/TyrusDynamicHTTP.java	Mon Dec 16 17:16:02 2013 +0100
   198.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   198.3 @@ -1,238 +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.wstyrus;
  198.25 -
  198.26 -import java.io.ByteArrayInputStream;
  198.27 -import java.io.ByteArrayOutputStream;
  198.28 -import java.io.IOException;
  198.29 -import java.io.InputStream;
  198.30 -import java.io.OutputStream;
  198.31 -import java.io.Reader;
  198.32 -import java.net.URI;
  198.33 -import java.net.URISyntaxException;
  198.34 -import java.util.ArrayList;
  198.35 -import java.util.List;
  198.36 -import java.util.logging.Level;
  198.37 -import java.util.logging.Logger;
  198.38 -import org.glassfish.grizzly.PortRange;
  198.39 -import org.glassfish.grizzly.http.server.HttpHandler;
  198.40 -import org.glassfish.grizzly.http.server.HttpServer;
  198.41 -import org.glassfish.grizzly.http.server.NetworkListener;
  198.42 -import org.glassfish.grizzly.http.server.Request;
  198.43 -import org.glassfish.grizzly.http.server.Response;
  198.44 -import org.glassfish.grizzly.http.server.ServerConfiguration;
  198.45 -import org.glassfish.grizzly.websockets.WebSocket;
  198.46 -import org.glassfish.grizzly.websockets.WebSocketAddOn;
  198.47 -import org.glassfish.grizzly.websockets.WebSocketApplication;
  198.48 -import org.glassfish.grizzly.websockets.WebSocketEngine;
  198.49 -
  198.50 -/**
  198.51 - *
  198.52 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  198.53 - */
  198.54 -final class TyrusDynamicHTTP extends HttpHandler {
  198.55 -    private static int resourcesCount;
  198.56 -    private static List<Resource> resources;
  198.57 -    private static ServerConfiguration conf;
  198.58 -    private static HttpServer server;
  198.59 -    
  198.60 -    private TyrusDynamicHTTP() {
  198.61 -    }
  198.62 -    
  198.63 -    static URI initServer() throws Exception {
  198.64 -        server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
  198.65 -        final WebSocketAddOn addon = new WebSocketAddOn();
  198.66 -        for (NetworkListener listener : server.getListeners()) {
  198.67 -            listener.registerAddOn(addon);
  198.68 -        }        
  198.69 -        resources = new ArrayList<Resource>();
  198.70 -
  198.71 -        conf = server.getServerConfiguration();
  198.72 -        final TyrusDynamicHTTP dh = new TyrusDynamicHTTP();
  198.73 -
  198.74 -        conf.addHttpHandler(dh, "/");
  198.75 -        
  198.76 -        server.start();
  198.77 -
  198.78 -        return pageURL("http", server, "/test.html");
  198.79 -    }
  198.80 -    
  198.81 -    @Override
  198.82 -    public void service(Request request, Response response) throws Exception {
  198.83 -        if ("/test.html".equals(request.getRequestURI())) {
  198.84 -            response.setContentType("text/html");
  198.85 -            final InputStream is = TyrusDynamicHTTP.class.getResourceAsStream("test.html");
  198.86 -            copyStream(is, response.getOutputStream(), null);
  198.87 -            return;
  198.88 -        }
  198.89 -        if ("/dynamic".equals(request.getRequestURI())) {
  198.90 -            String mimeType = request.getParameter("mimeType");
  198.91 -            List<String> params = new ArrayList<String>();
  198.92 -            boolean webSocket = false;
  198.93 -            for (int i = 0;; i++) {
  198.94 -                String p = request.getParameter("param" + i);
  198.95 -                if (p == null) {
  198.96 -                    break;
  198.97 -                }
  198.98 -                if ("protocol:ws".equals(p)) {
  198.99 -                    webSocket = true;
 198.100 -                    continue;
 198.101 -                }
 198.102 -                params.add(p);
 198.103 -            }
 198.104 -            final String cnt = request.getParameter("content");
 198.105 -            String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
 198.106 -            ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
 198.107 -            URI url;
 198.108 -            final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
 198.109 -            if (webSocket) {
 198.110 -                url = registerWebSocket(res);
 198.111 -            } else {
 198.112 -                url = registerResource(res);
 198.113 -            }
 198.114 -            response.getWriter().write(url.toString());
 198.115 -            response.getWriter().write("\n");
 198.116 -            return;
 198.117 -        }
 198.118 -
 198.119 -        for (Resource r : resources) {
 198.120 -            if (r.httpPath.equals(request.getRequestURI())) {
 198.121 -                response.setContentType(r.httpType);
 198.122 -                r.httpContent.reset();
 198.123 -                String[] params = null;
 198.124 -                if (r.parameters.length != 0) {
 198.125 -                    params = new String[r.parameters.length];
 198.126 -                    for (int i = 0; i < r.parameters.length; i++) {
 198.127 -                        params[i] = request.getParameter(r.parameters[i]);
 198.128 -                        if (params[i] == null) {
 198.129 -                            if ("http.method".equals(r.parameters[i])) {
 198.130 -                                params[i] = request.getMethod().toString();
 198.131 -                            } else if ("http.requestBody".equals(r.parameters[i])) {
 198.132 -                                Reader rdr = request.getReader();
 198.133 -                                StringBuilder sb = new StringBuilder();
 198.134 -                                for (;;) {
 198.135 -                                    int ch = rdr.read();
 198.136 -                                    if (ch == -1) {
 198.137 -                                        break;
 198.138 -                                    }
 198.139 -                                    sb.append((char) ch);
 198.140 -                                }
 198.141 -                                params[i] = sb.toString();
 198.142 -                            }
 198.143 -                        }
 198.144 -                        if (params[i] == null) {
 198.145 -                            params[i] = "null";
 198.146 -                        }
 198.147 -                    }
 198.148 -                }
 198.149 -
 198.150 -                copyStream(r.httpContent, response.getOutputStream(), null, params);
 198.151 -            }
 198.152 -        }
 198.153 -    }
 198.154 -    
 198.155 -    private URI registerWebSocket(Resource r) {
 198.156 -        WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
 198.157 -        return pageURL("ws", server, r.httpPath);
 198.158 -    }
 198.159 -
 198.160 -    private URI registerResource(Resource r) {
 198.161 -        if (!resources.contains(r)) {
 198.162 -            resources.add(r);
 198.163 -            conf.addHttpHandler(this, r.httpPath);
 198.164 -        }
 198.165 -        return pageURL("http", server, r.httpPath);
 198.166 -    }
 198.167 -    
 198.168 -    private static URI pageURL(String proto, HttpServer server, final String page) {
 198.169 -        NetworkListener listener = server.getListeners().iterator().next();
 198.170 -        int port = listener.getPort();
 198.171 -        try {
 198.172 -            return new URI(proto + "://localhost:" + port + page);
 198.173 -        } catch (URISyntaxException ex) {
 198.174 -            throw new IllegalStateException(ex);
 198.175 -        }
 198.176 -    }
 198.177 -    
 198.178 -    static final class Resource {
 198.179 -
 198.180 -        final InputStream httpContent;
 198.181 -        final String httpType;
 198.182 -        final String httpPath;
 198.183 -        final String[] parameters;
 198.184 -
 198.185 -        Resource(InputStream httpContent, String httpType, String httpPath,
 198.186 -            String[] parameters) {
 198.187 -            httpContent.mark(Integer.MAX_VALUE);
 198.188 -            this.httpContent = httpContent;
 198.189 -            this.httpType = httpType;
 198.190 -            this.httpPath = httpPath;
 198.191 -            this.parameters = parameters;
 198.192 -        }
 198.193 -    }
 198.194 -
 198.195 -    static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
 198.196 -        for (;;) {
 198.197 -            int ch = is.read();
 198.198 -            if (ch == -1) {
 198.199 -                break;
 198.200 -            }
 198.201 -            if (ch == '$' && params.length > 0) {
 198.202 -                int cnt = is.read() - '0';
 198.203 -                if (baseURL != null && cnt == 'U' - '0') {
 198.204 -                    os.write(baseURL.getBytes("UTF-8"));
 198.205 -                } else {
 198.206 -                    if (cnt >= 0 && cnt < params.length) {
 198.207 -                        os.write(params[cnt].getBytes("UTF-8"));
 198.208 -                    } else {
 198.209 -                        os.write('$');
 198.210 -                        os.write(cnt + '0');
 198.211 -                    }
 198.212 -                }
 198.213 -            } else {
 198.214 -                os.write(ch);
 198.215 -            }
 198.216 -        }
 198.217 -    }
 198.218 -    
 198.219 -    private static class WS extends WebSocketApplication {
 198.220 -        private final Resource r;
 198.221 -
 198.222 -        private WS(Resource r) {
 198.223 -            this.r = r;
 198.224 -        }
 198.225 -
 198.226 -        @Override
 198.227 -        public void onMessage(WebSocket socket, String text) {
 198.228 -            try {
 198.229 -                r.httpContent.reset();
 198.230 -                ByteArrayOutputStream out = new ByteArrayOutputStream();
 198.231 -                copyStream(r.httpContent, out, null, text);
 198.232 -                String s = new String(out.toByteArray(), "UTF-8");
 198.233 -                socket.send(s);
 198.234 -            } catch (IOException ex) {
 198.235 -                LOG.log(Level.WARNING, null, ex);
 198.236 -            }
 198.237 -        }
 198.238 -        private static final Logger LOG = Logger.getLogger(WS.class.getName());
 198.239 -        
 198.240 -    }
 198.241 -}
   199.1 --- a/ko-ws-tyrus/src/test/java/org/apidesign/html/wstyrus/TyrusFX.java	Mon Dec 16 17:16:02 2013 +0100
   199.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   199.3 @@ -1,98 +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.wstyrus;
  199.25 -
  199.26 -import java.lang.reflect.InvocationTargetException;
  199.27 -import java.lang.reflect.Method;
  199.28 -import javafx.application.Platform;
  199.29 -import org.apidesign.html.boot.impl.FnContext;
  199.30 -import org.apidesign.html.boot.spi.Fn;
  199.31 -import org.testng.ITest;
  199.32 -import org.testng.annotations.Test;
  199.33 -
  199.34 -/**
  199.35 - *
  199.36 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  199.37 - */
  199.38 -public final class TyrusFX implements ITest, Runnable {
  199.39 -    private final Fn.Presenter p;
  199.40 -    private final Method m;
  199.41 -    private Object result;
  199.42 -    private Object inst;
  199.43 -    private int count;
  199.44 -
  199.45 -    TyrusFX(Fn.Presenter p, Method m) {
  199.46 -        this.p = p;
  199.47 -        this.m = m;
  199.48 -    }
  199.49 -
  199.50 -    @Override
  199.51 -    public String getTestName() {
  199.52 -        return m.getName();
  199.53 -    }
  199.54 -
  199.55 -    @Test
  199.56 -    public synchronized void executeTest() throws Exception {
  199.57 -        if (result == null) {
  199.58 -            Platform.runLater(this);
  199.59 -            wait();
  199.60 -        }
  199.61 -        if (result instanceof Exception) {
  199.62 -            throw (Exception)result;
  199.63 -        }
  199.64 -        if (result instanceof Error) {
  199.65 -            throw (Error)result;
  199.66 -        }
  199.67 -    }
  199.68 -
  199.69 -    @Override
  199.70 -    public synchronized void run() {
  199.71 -        boolean notify = true;
  199.72 -        try {
  199.73 -            FnContext.currentPresenter(p);
  199.74 -            if (inst == null) {
  199.75 -                inst = m.getDeclaringClass().newInstance();
  199.76 -            }
  199.77 -            result = m.invoke(inst);
  199.78 -            if (result == null) {
  199.79 -                result = this;
  199.80 -            }
  199.81 -        } catch (InvocationTargetException ex) {
  199.82 -            Throwable r = ex.getTargetException();
  199.83 -            if (r instanceof InterruptedException) {
  199.84 -                if (count++ < 10000) {
  199.85 -                    notify = false;
  199.86 -                    Platform.runLater(this);
  199.87 -                    return;
  199.88 -                }
  199.89 -            }
  199.90 -            result = r;
  199.91 -        } catch (Exception ex) {
  199.92 -            result = ex;
  199.93 -        } finally {
  199.94 -            if (notify) {
  199.95 -                notifyAll();
  199.96 -            }
  199.97 -            FnContext.currentPresenter(null);
  199.98 -        }
  199.99 -    }
 199.100 -    
 199.101 -}
   200.1 --- a/ko-ws-tyrus/src/test/java/org/apidesign/html/wstyrus/TyrusKnockoutTest.java	Mon Dec 16 17:16:02 2013 +0100
   200.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   200.3 @@ -1,191 +0,0 @@
   200.4 -/**
   200.5 - * HTML via Java(tm) Language Bindings
   200.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   200.7 - *
   200.8 - * This program is free software: you can redistribute it and/or modify
   200.9 - * it under the terms of the GNU General Public License as published by
  200.10 - * the Free Software Foundation, version 2 of the License.
  200.11 - *
  200.12 - * This program is distributed in the hope that it will be useful,
  200.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  200.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  200.15 - * GNU General Public License for more details. apidesign.org
  200.16 - * designates this particular file as subject to the
  200.17 - * "Classpath" exception as provided by apidesign.org
  200.18 - * in the License file that accompanied this code.
  200.19 - *
  200.20 - * You should have received a copy of the GNU General Public License
  200.21 - * along with this program. Look for COPYING file in the top folder.
  200.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  200.23 - */
  200.24 -package org.apidesign.html.wstyrus;
  200.25 -
  200.26 -import java.io.BufferedReader;
  200.27 -import java.io.IOException;
  200.28 -import java.io.InputStreamReader;
  200.29 -import java.lang.annotation.Annotation;
  200.30 -import java.lang.reflect.Method;
  200.31 -import java.net.URI;
  200.32 -import java.net.URISyntaxException;
  200.33 -import java.net.URL;
  200.34 -import java.net.URLConnection;
  200.35 -import java.util.ArrayList;
  200.36 -import java.util.List;
  200.37 -import java.util.Map;
  200.38 -import java.util.concurrent.Executors;
  200.39 -import net.java.html.BrwsrCtx;
  200.40 -import net.java.html.boot.BrowserBuilder;
  200.41 -import net.java.html.js.JavaScriptBody;
  200.42 -import org.apidesign.html.boot.impl.FnContext;
  200.43 -import org.apidesign.html.boot.impl.FnUtils;
  200.44 -import org.apidesign.html.boot.spi.Fn;
  200.45 -import org.apidesign.html.context.spi.Contexts;
  200.46 -import org.apidesign.html.json.spi.Technology;
  200.47 -import org.apidesign.html.json.spi.Transfer;
  200.48 -import org.apidesign.html.json.spi.WSTransfer;
  200.49 -import org.apidesign.html.json.tck.KOTest;
  200.50 -import org.apidesign.html.json.tck.KnockoutTCK;
  200.51 -import org.apidesign.html.kofx.FXContext;
  200.52 -import org.json.JSONException;
  200.53 -import org.json.JSONObject;
  200.54 -import org.openide.util.lookup.ServiceProvider;
  200.55 -import org.testng.annotations.Factory;
  200.56 -import static org.testng.Assert.*;
  200.57 -
  200.58 -/**
  200.59 - *
  200.60 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  200.61 - */
  200.62 -@ServiceProvider(service = KnockoutTCK.class)
  200.63 -public final class TyrusKnockoutTest extends KnockoutTCK {
  200.64 -    private static Class<?> browserClass;
  200.65 -    private static Fn.Presenter browserContext;
  200.66 -    
  200.67 -    public TyrusKnockoutTest() {
  200.68 -    }
  200.69 -    
  200.70 -    @Factory public static Object[] compatibilityTests() throws Exception {
  200.71 -        Class[] arr = testClasses();
  200.72 -        for (int i = 0; i < arr.length; i++) {
  200.73 -            assertEquals(
  200.74 -                arr[i].getClassLoader(),
  200.75 -                TyrusKnockoutTest.class.getClassLoader(),
  200.76 -                "All classes loaded by the same classloader"
  200.77 -            );
  200.78 -        }
  200.79 -        
  200.80 -        URI uri = TyrusDynamicHTTP.initServer();
  200.81 -    
  200.82 -        final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(TyrusKnockoutTest.class).
  200.83 -            loadPage(uri.toString()).
  200.84 -            invoke("initialized");
  200.85 -        
  200.86 -        Executors.newSingleThreadExecutor().submit(new Runnable() {
  200.87 -            @Override
  200.88 -            public void run() {
  200.89 -                bb.showAndWait();
  200.90 -            }
  200.91 -        });
  200.92 -        
  200.93 -        ClassLoader l = getClassLoader();
  200.94 -        List<Object> res = new ArrayList<Object>();
  200.95 -        for (int i = 0; i < arr.length; i++) {
  200.96 -            Class<?> c = Class.forName(arr[i].getName(), true, l);
  200.97 -            Class<? extends Annotation> koTest = 
  200.98 -                c.getClassLoader().loadClass(KOTest.class.getName()).
  200.99 -                asSubclass(Annotation.class);
 200.100 -            for (Method m : c.getMethods()) {
 200.101 -                if (m.getAnnotation(koTest) != null) {
 200.102 -                    res.add(new TyrusFX(browserContext, m));
 200.103 -                }
 200.104 -            }
 200.105 -        }
 200.106 -        return res.toArray();
 200.107 -    }
 200.108 -
 200.109 -    static synchronized ClassLoader getClassLoader() throws InterruptedException {
 200.110 -        while (browserClass == null) {
 200.111 -            TyrusKnockoutTest.class.wait();
 200.112 -        }
 200.113 -        return browserClass.getClassLoader();
 200.114 -    }
 200.115 -    
 200.116 -    public static synchronized void initialized(Class<?> browserCls) throws Exception {
 200.117 -        browserClass = browserCls;
 200.118 -        browserContext = FnContext.currentPresenter();
 200.119 -        TyrusKnockoutTest.class.notifyAll();
 200.120 -    }
 200.121 -    
 200.122 -    public static void initialized() throws Exception {
 200.123 -        Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(TyrusKnockoutTest.class.getName());
 200.124 -        Method m = classpathClass.getMethod("initialized", Class.class);
 200.125 -        m.invoke(null, TyrusKnockoutTest.class);
 200.126 -        browserContext = FnContext.currentPresenter();
 200.127 -    }
 200.128 -    
 200.129 -    @Override
 200.130 -    public BrwsrCtx createContext() {
 200.131 -        FXContext fx = new FXContext(browserContext);
 200.132 -        TyrusContext tc = new TyrusContext();
 200.133 -        Contexts.Builder cb = Contexts.newBuilder().
 200.134 -            register(Technology.class, fx, 10).
 200.135 -            register(Transfer.class, fx, 10).
 200.136 -            register(WSTransfer.class, tc, 10);
 200.137 -        return cb.build();
 200.138 -    }
 200.139 -
 200.140 -    @Override
 200.141 -    public Object createJSON(Map<String, Object> values) {
 200.142 -        JSONObject json = new JSONObject();
 200.143 -        for (Map.Entry<String, Object> entry : values.entrySet()) {
 200.144 -            try {
 200.145 -                json.put(entry.getKey(), entry.getValue());
 200.146 -            } catch (JSONException ex) {
 200.147 -                throw new IllegalStateException(ex);
 200.148 -            }
 200.149 -        }
 200.150 -        return json;
 200.151 -    }
 200.152 -
 200.153 -    @Override
 200.154 -    @JavaScriptBody(args = { "s", "args" }, body = ""
 200.155 -        + "var f = new Function(s); "
 200.156 -        + "return f.apply(null, args);"
 200.157 -    )
 200.158 -    public native Object executeScript(String script, Object[] arguments);
 200.159 -
 200.160 -    @JavaScriptBody(args = {  }, body = 
 200.161 -          "var h;"
 200.162 -        + "if (!!window && !!window.location && !!window.location.href)\n"
 200.163 -        + "  h = window.location.href;\n"
 200.164 -        + "else "
 200.165 -        + "  h = null;"
 200.166 -        + "return h;\n"
 200.167 -    )
 200.168 -    private static native String findBaseURL();
 200.169 -    
 200.170 -    @Override
 200.171 -    public URI prepareURL(String content, String mimeType, String[] parameters) {
 200.172 -        try {
 200.173 -            final URL baseURL = new URL(findBaseURL());
 200.174 -            StringBuilder sb = new StringBuilder();
 200.175 -            sb.append("/dynamic?mimeType=").append(mimeType);
 200.176 -            for (int i = 0; i < parameters.length; i++) {
 200.177 -                sb.append("&param" + i).append("=").append(parameters[i]);
 200.178 -            }
 200.179 -            String mangle = content.replace("\n", "%0a")
 200.180 -                .replace("\"", "\\\"").replace(" ", "%20");
 200.181 -            sb.append("&content=").append(mangle);
 200.182 -
 200.183 -            URL query = new URL(baseURL, sb.toString());
 200.184 -            URLConnection c = query.openConnection();
 200.185 -            BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
 200.186 -            URI connectTo = new URI(br.readLine());
 200.187 -            return connectTo;
 200.188 -        } catch (IOException ex) {
 200.189 -            throw new IllegalStateException(ex);
 200.190 -        } catch (URISyntaxException ex) {
 200.191 -            throw new IllegalStateException(ex);
 200.192 -        }
 200.193 -    }
 200.194 -}
   201.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   201.2 +++ b/ko-ws-tyrus/src/test/java/org/netbeans/html/wstyrus/TyrusDynamicHTTP.java	Mon Dec 16 17:16:40 2013 +0100
   201.3 @@ -0,0 +1,260 @@
   201.4 +/**
   201.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   201.6 + *
   201.7 + * Copyright 1997-2010 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.wstyrus;
  201.47 +
  201.48 +import java.io.ByteArrayInputStream;
  201.49 +import java.io.ByteArrayOutputStream;
  201.50 +import java.io.IOException;
  201.51 +import java.io.InputStream;
  201.52 +import java.io.OutputStream;
  201.53 +import java.io.Reader;
  201.54 +import java.net.URI;
  201.55 +import java.net.URISyntaxException;
  201.56 +import java.util.ArrayList;
  201.57 +import java.util.List;
  201.58 +import java.util.logging.Level;
  201.59 +import java.util.logging.Logger;
  201.60 +import org.glassfish.grizzly.PortRange;
  201.61 +import org.glassfish.grizzly.http.server.HttpHandler;
  201.62 +import org.glassfish.grizzly.http.server.HttpServer;
  201.63 +import org.glassfish.grizzly.http.server.NetworkListener;
  201.64 +import org.glassfish.grizzly.http.server.Request;
  201.65 +import org.glassfish.grizzly.http.server.Response;
  201.66 +import org.glassfish.grizzly.http.server.ServerConfiguration;
  201.67 +import org.glassfish.grizzly.websockets.WebSocket;
  201.68 +import org.glassfish.grizzly.websockets.WebSocketAddOn;
  201.69 +import org.glassfish.grizzly.websockets.WebSocketApplication;
  201.70 +import org.glassfish.grizzly.websockets.WebSocketEngine;
  201.71 +
  201.72 +/**
  201.73 + *
  201.74 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  201.75 + */
  201.76 +final class TyrusDynamicHTTP extends HttpHandler {
  201.77 +    private static int resourcesCount;
  201.78 +    private static List<Resource> resources;
  201.79 +    private static ServerConfiguration conf;
  201.80 +    private static HttpServer server;
  201.81 +    
  201.82 +    private TyrusDynamicHTTP() {
  201.83 +    }
  201.84 +    
  201.85 +    static URI initServer() throws Exception {
  201.86 +        server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
  201.87 +        final WebSocketAddOn addon = new WebSocketAddOn();
  201.88 +        for (NetworkListener listener : server.getListeners()) {
  201.89 +            listener.registerAddOn(addon);
  201.90 +        }        
  201.91 +        resources = new ArrayList<Resource>();
  201.92 +
  201.93 +        conf = server.getServerConfiguration();
  201.94 +        final TyrusDynamicHTTP dh = new TyrusDynamicHTTP();
  201.95 +
  201.96 +        conf.addHttpHandler(dh, "/");
  201.97 +        
  201.98 +        server.start();
  201.99 +
 201.100 +        return pageURL("http", server, "/test.html");
 201.101 +    }
 201.102 +    
 201.103 +    @Override
 201.104 +    public void service(Request request, Response response) throws Exception {
 201.105 +        if ("/test.html".equals(request.getRequestURI())) {
 201.106 +            response.setContentType("text/html");
 201.107 +            final InputStream is = TyrusDynamicHTTP.class.getResourceAsStream("test.html");
 201.108 +            copyStream(is, response.getOutputStream(), null);
 201.109 +            return;
 201.110 +        }
 201.111 +        if ("/dynamic".equals(request.getRequestURI())) {
 201.112 +            String mimeType = request.getParameter("mimeType");
 201.113 +            List<String> params = new ArrayList<String>();
 201.114 +            boolean webSocket = false;
 201.115 +            for (int i = 0;; i++) {
 201.116 +                String p = request.getParameter("param" + i);
 201.117 +                if (p == null) {
 201.118 +                    break;
 201.119 +                }
 201.120 +                if ("protocol:ws".equals(p)) {
 201.121 +                    webSocket = true;
 201.122 +                    continue;
 201.123 +                }
 201.124 +                params.add(p);
 201.125 +            }
 201.126 +            final String cnt = request.getParameter("content");
 201.127 +            String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
 201.128 +            ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
 201.129 +            URI url;
 201.130 +            final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
 201.131 +            if (webSocket) {
 201.132 +                url = registerWebSocket(res);
 201.133 +            } else {
 201.134 +                url = registerResource(res);
 201.135 +            }
 201.136 +            response.getWriter().write(url.toString());
 201.137 +            response.getWriter().write("\n");
 201.138 +            return;
 201.139 +        }
 201.140 +
 201.141 +        for (Resource r : resources) {
 201.142 +            if (r.httpPath.equals(request.getRequestURI())) {
 201.143 +                response.setContentType(r.httpType);
 201.144 +                r.httpContent.reset();
 201.145 +                String[] params = null;
 201.146 +                if (r.parameters.length != 0) {
 201.147 +                    params = new String[r.parameters.length];
 201.148 +                    for (int i = 0; i < r.parameters.length; i++) {
 201.149 +                        params[i] = request.getParameter(r.parameters[i]);
 201.150 +                        if (params[i] == null) {
 201.151 +                            if ("http.method".equals(r.parameters[i])) {
 201.152 +                                params[i] = request.getMethod().toString();
 201.153 +                            } else if ("http.requestBody".equals(r.parameters[i])) {
 201.154 +                                Reader rdr = request.getReader();
 201.155 +                                StringBuilder sb = new StringBuilder();
 201.156 +                                for (;;) {
 201.157 +                                    int ch = rdr.read();
 201.158 +                                    if (ch == -1) {
 201.159 +                                        break;
 201.160 +                                    }
 201.161 +                                    sb.append((char) ch);
 201.162 +                                }
 201.163 +                                params[i] = sb.toString();
 201.164 +                            }
 201.165 +                        }
 201.166 +                        if (params[i] == null) {
 201.167 +                            params[i] = "null";
 201.168 +                        }
 201.169 +                    }
 201.170 +                }
 201.171 +
 201.172 +                copyStream(r.httpContent, response.getOutputStream(), null, params);
 201.173 +            }
 201.174 +        }
 201.175 +    }
 201.176 +    
 201.177 +    private URI registerWebSocket(Resource r) {
 201.178 +        WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
 201.179 +        return pageURL("ws", server, r.httpPath);
 201.180 +    }
 201.181 +
 201.182 +    private URI registerResource(Resource r) {
 201.183 +        if (!resources.contains(r)) {
 201.184 +            resources.add(r);
 201.185 +            conf.addHttpHandler(this, r.httpPath);
 201.186 +        }
 201.187 +        return pageURL("http", server, r.httpPath);
 201.188 +    }
 201.189 +    
 201.190 +    private static URI pageURL(String proto, HttpServer server, final String page) {
 201.191 +        NetworkListener listener = server.getListeners().iterator().next();
 201.192 +        int port = listener.getPort();
 201.193 +        try {
 201.194 +            return new URI(proto + "://localhost:" + port + page);
 201.195 +        } catch (URISyntaxException ex) {
 201.196 +            throw new IllegalStateException(ex);
 201.197 +        }
 201.198 +    }
 201.199 +    
 201.200 +    static final class Resource {
 201.201 +
 201.202 +        final InputStream httpContent;
 201.203 +        final String httpType;
 201.204 +        final String httpPath;
 201.205 +        final String[] parameters;
 201.206 +
 201.207 +        Resource(InputStream httpContent, String httpType, String httpPath,
 201.208 +            String[] parameters) {
 201.209 +            httpContent.mark(Integer.MAX_VALUE);
 201.210 +            this.httpContent = httpContent;
 201.211 +            this.httpType = httpType;
 201.212 +            this.httpPath = httpPath;
 201.213 +            this.parameters = parameters;
 201.214 +        }
 201.215 +    }
 201.216 +
 201.217 +    static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
 201.218 +        for (;;) {
 201.219 +            int ch = is.read();
 201.220 +            if (ch == -1) {
 201.221 +                break;
 201.222 +            }
 201.223 +            if (ch == '$' && params.length > 0) {
 201.224 +                int cnt = is.read() - '0';
 201.225 +                if (baseURL != null && cnt == 'U' - '0') {
 201.226 +                    os.write(baseURL.getBytes("UTF-8"));
 201.227 +                } else {
 201.228 +                    if (cnt >= 0 && cnt < params.length) {
 201.229 +                        os.write(params[cnt].getBytes("UTF-8"));
 201.230 +                    } else {
 201.231 +                        os.write('$');
 201.232 +                        os.write(cnt + '0');
 201.233 +                    }
 201.234 +                }
 201.235 +            } else {
 201.236 +                os.write(ch);
 201.237 +            }
 201.238 +        }
 201.239 +    }
 201.240 +    
 201.241 +    private static class WS extends WebSocketApplication {
 201.242 +        private final Resource r;
 201.243 +
 201.244 +        private WS(Resource r) {
 201.245 +            this.r = r;
 201.246 +        }
 201.247 +
 201.248 +        @Override
 201.249 +        public void onMessage(WebSocket socket, String text) {
 201.250 +            try {
 201.251 +                r.httpContent.reset();
 201.252 +                ByteArrayOutputStream out = new ByteArrayOutputStream();
 201.253 +                copyStream(r.httpContent, out, null, text);
 201.254 +                String s = new String(out.toByteArray(), "UTF-8");
 201.255 +                socket.send(s);
 201.256 +            } catch (IOException ex) {
 201.257 +                LOG.log(Level.WARNING, null, ex);
 201.258 +            }
 201.259 +        }
 201.260 +        private static final Logger LOG = Logger.getLogger(WS.class.getName());
 201.261 +        
 201.262 +    }
 201.263 +}
   202.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   202.2 +++ b/ko-ws-tyrus/src/test/java/org/netbeans/html/wstyrus/TyrusFX.java	Mon Dec 16 17:16:40 2013 +0100
   202.3 @@ -0,0 +1,120 @@
   202.4 +/**
   202.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   202.6 + *
   202.7 + * Copyright 1997-2010 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.wstyrus;
  202.47 +
  202.48 +import java.lang.reflect.InvocationTargetException;
  202.49 +import java.lang.reflect.Method;
  202.50 +import javafx.application.Platform;
  202.51 +import org.netbeans.html.boot.impl.FnContext;
  202.52 +import org.apidesign.html.boot.spi.Fn;
  202.53 +import org.testng.ITest;
  202.54 +import org.testng.annotations.Test;
  202.55 +
  202.56 +/**
  202.57 + *
  202.58 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  202.59 + */
  202.60 +public final class TyrusFX implements ITest, Runnable {
  202.61 +    private final Fn.Presenter p;
  202.62 +    private final Method m;
  202.63 +    private Object result;
  202.64 +    private Object inst;
  202.65 +    private int count;
  202.66 +
  202.67 +    TyrusFX(Fn.Presenter p, Method m) {
  202.68 +        this.p = p;
  202.69 +        this.m = m;
  202.70 +    }
  202.71 +
  202.72 +    @Override
  202.73 +    public String getTestName() {
  202.74 +        return m.getName();
  202.75 +    }
  202.76 +
  202.77 +    @Test
  202.78 +    public synchronized void executeTest() throws Exception {
  202.79 +        if (result == null) {
  202.80 +            Platform.runLater(this);
  202.81 +            wait();
  202.82 +        }
  202.83 +        if (result instanceof Exception) {
  202.84 +            throw (Exception)result;
  202.85 +        }
  202.86 +        if (result instanceof Error) {
  202.87 +            throw (Error)result;
  202.88 +        }
  202.89 +    }
  202.90 +
  202.91 +    @Override
  202.92 +    public synchronized void run() {
  202.93 +        boolean notify = true;
  202.94 +        try {
  202.95 +            FnContext.currentPresenter(p);
  202.96 +            if (inst == null) {
  202.97 +                inst = m.getDeclaringClass().newInstance();
  202.98 +            }
  202.99 +            result = m.invoke(inst);
 202.100 +            if (result == null) {
 202.101 +                result = this;
 202.102 +            }
 202.103 +        } catch (InvocationTargetException ex) {
 202.104 +            Throwable r = ex.getTargetException();
 202.105 +            if (r instanceof InterruptedException) {
 202.106 +                if (count++ < 10000) {
 202.107 +                    notify = false;
 202.108 +                    Platform.runLater(this);
 202.109 +                    return;
 202.110 +                }
 202.111 +            }
 202.112 +            result = r;
 202.113 +        } catch (Exception ex) {
 202.114 +            result = ex;
 202.115 +        } finally {
 202.116 +            if (notify) {
 202.117 +                notifyAll();
 202.118 +            }
 202.119 +            FnContext.currentPresenter(null);
 202.120 +        }
 202.121 +    }
 202.122 +    
 202.123 +}
   203.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   203.2 +++ b/ko-ws-tyrus/src/test/java/org/netbeans/html/wstyrus/TyrusKnockoutTest.java	Mon Dec 16 17:16:40 2013 +0100
   203.3 @@ -0,0 +1,212 @@
   203.4 +/**
   203.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   203.6 + *
   203.7 + * Copyright 1997-2010 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.wstyrus;
  203.47 +
  203.48 +import java.io.BufferedReader;
  203.49 +import java.io.IOException;
  203.50 +import java.io.InputStreamReader;
  203.51 +import java.lang.annotation.Annotation;
  203.52 +import java.lang.reflect.Method;
  203.53 +import java.net.URI;
  203.54 +import java.net.URISyntaxException;
  203.55 +import java.net.URL;
  203.56 +import java.net.URLConnection;
  203.57 +import java.util.ArrayList;
  203.58 +import java.util.List;
  203.59 +import java.util.Map;
  203.60 +import java.util.concurrent.Executors;
  203.61 +import net.java.html.BrwsrCtx;
  203.62 +import net.java.html.boot.BrowserBuilder;
  203.63 +import net.java.html.js.JavaScriptBody;
  203.64 +import org.netbeans.html.boot.impl.FnContext;
  203.65 +import org.apidesign.html.boot.spi.Fn;
  203.66 +import org.apidesign.html.context.spi.Contexts;
  203.67 +import org.apidesign.html.json.spi.Technology;
  203.68 +import org.apidesign.html.json.spi.Transfer;
  203.69 +import org.apidesign.html.json.spi.WSTransfer;
  203.70 +import org.apidesign.html.json.tck.KOTest;
  203.71 +import org.apidesign.html.json.tck.KnockoutTCK;
  203.72 +import org.json.JSONException;
  203.73 +import org.json.JSONObject;
  203.74 +import org.netbeans.html.kofx.FXContext;
  203.75 +import org.openide.util.lookup.ServiceProvider;
  203.76 +import org.testng.annotations.Factory;
  203.77 +import static org.testng.Assert.*;
  203.78 +
  203.79 +/**
  203.80 + *
  203.81 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  203.82 + */
  203.83 +@ServiceProvider(service = KnockoutTCK.class)
  203.84 +public final class TyrusKnockoutTest extends KnockoutTCK {
  203.85 +    private static Class<?> browserClass;
  203.86 +    private static Fn.Presenter browserContext;
  203.87 +    
  203.88 +    public TyrusKnockoutTest() {
  203.89 +    }
  203.90 +    
  203.91 +    @Factory public static Object[] compatibilityTests() throws Exception {
  203.92 +        Class[] arr = testClasses();
  203.93 +        for (int i = 0; i < arr.length; i++) {
  203.94 +            assertEquals(
  203.95 +                arr[i].getClassLoader(),
  203.96 +                TyrusKnockoutTest.class.getClassLoader(),
  203.97 +                "All classes loaded by the same classloader"
  203.98 +            );
  203.99 +        }
 203.100 +        
 203.101 +        URI uri = TyrusDynamicHTTP.initServer();
 203.102 +    
 203.103 +        final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(TyrusKnockoutTest.class).
 203.104 +            loadPage(uri.toString()).
 203.105 +            invoke("initialized");
 203.106 +        
 203.107 +        Executors.newSingleThreadExecutor().submit(new Runnable() {
 203.108 +            @Override
 203.109 +            public void run() {
 203.110 +                bb.showAndWait();
 203.111 +            }
 203.112 +        });
 203.113 +        
 203.114 +        ClassLoader l = getClassLoader();
 203.115 +        List<Object> res = new ArrayList<Object>();
 203.116 +        for (int i = 0; i < arr.length; i++) {
 203.117 +            Class<?> c = Class.forName(arr[i].getName(), true, l);
 203.118 +            Class<? extends Annotation> koTest = 
 203.119 +                c.getClassLoader().loadClass(KOTest.class.getName()).
 203.120 +                asSubclass(Annotation.class);
 203.121 +            for (Method m : c.getMethods()) {
 203.122 +                if (m.getAnnotation(koTest) != null) {
 203.123 +                    res.add(new TyrusFX(browserContext, m));
 203.124 +                }
 203.125 +            }
 203.126 +        }
 203.127 +        return res.toArray();
 203.128 +    }
 203.129 +
 203.130 +    static synchronized ClassLoader getClassLoader() throws InterruptedException {
 203.131 +        while (browserClass == null) {
 203.132 +            TyrusKnockoutTest.class.wait();
 203.133 +        }
 203.134 +        return browserClass.getClassLoader();
 203.135 +    }
 203.136 +    
 203.137 +    public static synchronized void initialized(Class<?> browserCls) throws Exception {
 203.138 +        browserClass = browserCls;
 203.139 +        browserContext = FnContext.currentPresenter();
 203.140 +        TyrusKnockoutTest.class.notifyAll();
 203.141 +    }
 203.142 +    
 203.143 +    public static void initialized() throws Exception {
 203.144 +        Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(TyrusKnockoutTest.class.getName());
 203.145 +        Method m = classpathClass.getMethod("initialized", Class.class);
 203.146 +        m.invoke(null, TyrusKnockoutTest.class);
 203.147 +        browserContext = FnContext.currentPresenter();
 203.148 +    }
 203.149 +    
 203.150 +    @Override
 203.151 +    public BrwsrCtx createContext() {
 203.152 +        FXContext fx = new FXContext(browserContext);
 203.153 +        TyrusContext tc = new TyrusContext();
 203.154 +        Contexts.Builder cb = Contexts.newBuilder().
 203.155 +            register(Technology.class, fx, 10).
 203.156 +            register(Transfer.class, fx, 10).
 203.157 +            register(WSTransfer.class, tc, 10);
 203.158 +        return cb.build();
 203.159 +    }
 203.160 +
 203.161 +    @Override
 203.162 +    public Object createJSON(Map<String, Object> values) {
 203.163 +        JSONObject json = new JSONObject();
 203.164 +        for (Map.Entry<String, Object> entry : values.entrySet()) {
 203.165 +            try {
 203.166 +                json.put(entry.getKey(), entry.getValue());
 203.167 +            } catch (JSONException ex) {
 203.168 +                throw new IllegalStateException(ex);
 203.169 +            }
 203.170 +        }
 203.171 +        return json;
 203.172 +    }
 203.173 +
 203.174 +    @Override
 203.175 +    @JavaScriptBody(args = { "s", "args" }, body = ""
 203.176 +        + "var f = new Function(s); "
 203.177 +        + "return f.apply(null, args);"
 203.178 +    )
 203.179 +    public native Object executeScript(String script, Object[] arguments);
 203.180 +
 203.181 +    @JavaScriptBody(args = {  }, body = 
 203.182 +          "var h;"
 203.183 +        + "if (!!window && !!window.location && !!window.location.href)\n"
 203.184 +        + "  h = window.location.href;\n"
 203.185 +        + "else "
 203.186 +        + "  h = null;"
 203.187 +        + "return h;\n"
 203.188 +    )
 203.189 +    private static native String findBaseURL();
 203.190 +    
 203.191 +    @Override
 203.192 +    public URI prepareURL(String content, String mimeType, String[] parameters) {
 203.193 +        try {
 203.194 +            final URL baseURL = new URL(findBaseURL());
 203.195 +            StringBuilder sb = new StringBuilder();
 203.196 +            sb.append("/dynamic?mimeType=").append(mimeType);
 203.197 +            for (int i = 0; i < parameters.length; i++) {
 203.198 +                sb.append("&param" + i).append("=").append(parameters[i]);
 203.199 +            }
 203.200 +            String mangle = content.replace("\n", "%0a")
 203.201 +                .replace("\"", "\\\"").replace(" ", "%20");
 203.202 +            sb.append("&content=").append(mangle);
 203.203 +
 203.204 +            URL query = new URL(baseURL, sb.toString());
 203.205 +            URLConnection c = query.openConnection();
 203.206 +            BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
 203.207 +            URI connectTo = new URI(br.readLine());
 203.208 +            return connectTo;
 203.209 +        } catch (IOException ex) {
 203.210 +            throw new IllegalStateException(ex);
 203.211 +        } catch (URISyntaxException ex) {
 203.212 +            throw new IllegalStateException(ex);
 203.213 +        }
 203.214 +    }
 203.215 +}
   204.1 --- a/ko-ws-tyrus/src/test/resources/org/apidesign/html/wstyrus/test.html	Mon Dec 16 17:16:02 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>Tyrus WebSockets 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>Tyrus WebSockets 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-ws-tyrus/src/test/resources/org/netbeans/html/wstyrus/test.html	Mon Dec 16 17:16:40 2013 +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 1997-2010 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>Tyrus WebSockets 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>Tyrus WebSockets Execution Harness</h1>
  205.57 +    </body>
  205.58 +    <script></script>
  205.59 +</html>
   206.1 --- a/pom.xml	Mon Dec 16 17:16:02 2013 +0100
   206.2 +++ b/pom.xml	Mon Dec 16 17:16:40 2013 +0100
   206.3 @@ -1,8 +1,8 @@
   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 -  <groupId>org.apidesign</groupId>
   206.8 -  <artifactId>html</artifactId>
   206.9 +  <groupId>org.netbeans.html</groupId>
  206.10 +  <artifactId>pom</artifactId>
  206.11    <version>0.7-SNAPSHOT</version>
  206.12    <packaging>pom</packaging>
  206.13    <name>HTML APIs via Java</name>
  206.14 @@ -16,6 +16,7 @@
  206.15        <netbeans.version>RELEASE73</netbeans.version>
  206.16        <license>COPYING</license>
  206.17        <publicPackages></publicPackages>
  206.18 +      <bundleSymbolicName>${project.artifactId}</bundleSymbolicName>
  206.19    </properties>
  206.20    <modules>
  206.21      <module>json</module>
  206.22 @@ -38,8 +39,8 @@
  206.23        </license>
  206.24    </licenses>
  206.25    <organization>
  206.26 -      <name>API Design</name>
  206.27 -      <url>http://apidesign.org</url>
  206.28 +      <name>NetBeans</name>
  206.29 +      <url>http://netbeans.org</url>
  206.30    </organization>
  206.31    <scm>
  206.32        <connection>scm:hg:https://hg.apidesign.org/hg/html~html4j</connection>
  206.33 @@ -91,7 +92,7 @@
  206.34                         <exclude>*</exclude>
  206.35                         <exclude>.*/**</exclude>
  206.36                         <exclude>ko-archetype/src/main/resources/**</exclude>
  206.37 -                       <exclude>ko-fx/src/main/resources/org/apidesign/html/kofx/knockout*.js</exclude>
  206.38 +                       <exclude>ko-fx/src/main/resources/org/netbeans/html/kofx/knockout*.js</exclude>
  206.39                    </excludes>
  206.40                </configuration>
  206.41            </plugin>
  206.42 @@ -139,7 +140,7 @@
  206.43                  <configuration>
  206.44                      <instructions>
  206.45                          <Export-Package>${publicPackages},META-INF.services.*</Export-Package>
  206.46 -                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
  206.47 +                        <Bundle-SymbolicName>${bundleSymbolicName}</Bundle-SymbolicName>
  206.48                      </instructions>
  206.49                  </configuration>
  206.50              </plugin>
   207.1 --- a/sound/pom.xml	Mon Dec 16 17:16:02 2013 +0100
   207.2 +++ b/sound/pom.xml	Mon Dec 16 17:16:40 2013 +0100
   207.3 @@ -2,11 +2,11 @@
   207.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">
   207.5      <modelVersion>4.0.0</modelVersion>
   207.6      <parent>
   207.7 -        <groupId>org.apidesign</groupId>
   207.8 -        <artifactId>html</artifactId>
   207.9 +        <groupId>org.netbeans.html</groupId>
  207.10 +        <artifactId>pom</artifactId>
  207.11          <version>0.7-SNAPSHOT</version>
  207.12      </parent>
  207.13 -    <groupId>org.apidesign.html</groupId>
  207.14 +    <groupId>org.netbeans.html</groupId>
  207.15      <artifactId>net.java.html.sound</artifactId>
  207.16      <version>0.7-SNAPSHOT</version>
  207.17      <packaging>bundle</packaging>
  207.18 @@ -31,7 +31,7 @@
  207.19              <scope>test</scope>
  207.20          </dependency>
  207.21          <dependency>
  207.22 -            <groupId>org.apidesign.html</groupId>
  207.23 +            <groupId>org.netbeans.html</groupId>
  207.24              <artifactId>net.java.html.boot</artifactId>
  207.25              <version>0.7-SNAPSHOT</version>
  207.26              <type>jar</type>
   208.1 --- a/sound/src/main/java/net/java/html/sound/AudioClip.java	Mon Dec 16 17:16:02 2013 +0100
   208.2 +++ b/sound/src/main/java/net/java/html/sound/AudioClip.java	Mon Dec 16 17:16:40 2013 +0100
   208.3 @@ -1,22 +1,44 @@
   208.4  /**
   208.5 - * HTML via Java(tm) Language Bindings
   208.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   208.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   208.8   *
   208.9 - * This program is free software: you can redistribute it and/or modify
  208.10 - * it under the terms of the GNU General Public License as published by
  208.11 - * the Free Software Foundation, version 2 of the License.
  208.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  208.13   *
  208.14 - * This program is distributed in the hope that it will be useful,
  208.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  208.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  208.17 - * GNU General Public License for more details. apidesign.org
  208.18 - * designates this particular file as subject to the
  208.19 - * "Classpath" exception as provided by apidesign.org
  208.20 - * in the License file that accompanied this code.
  208.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  208.22 + * Other names may be trademarks of their respective owners.
  208.23   *
  208.24 - * You should have received a copy of the GNU General Public License
  208.25 - * along with this program. Look for COPYING file in the top folder.
  208.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  208.27 + * The contents of this file are subject to the terms of either the GNU
  208.28 + * General Public License Version 2 only ("GPL") or the Common
  208.29 + * Development and Distribution License("CDDL") (collectively, the
  208.30 + * "License"). You may not use this file except in compliance with the
  208.31 + * License. You can obtain a copy of the License at
  208.32 + * http://www.netbeans.org/cddl-gplv2.html
  208.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  208.34 + * specific language governing permissions and limitations under the
  208.35 + * License.  When distributing the software, include this License Header
  208.36 + * Notice in each file and include the License file at
  208.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  208.38 + * particular file as subject to the "Classpath" exception as provided
  208.39 + * by Oracle in the GPL Version 2 section of the License file that
  208.40 + * accompanied this code. If applicable, add the following below the
  208.41 + * License Header, with the fields enclosed by brackets [] replaced by
  208.42 + * your own identifying information:
  208.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  208.44 + *
  208.45 + * Contributor(s):
  208.46 + *
  208.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  208.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  208.49 + *
  208.50 + * If you wish your version of this file to be governed by only the CDDL
  208.51 + * or only the GPL Version 2, indicate your decision by adding
  208.52 + * "[Contributor] elects to include this software in this distribution
  208.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  208.54 + * single choice of license, a recipient has the option to distribute
  208.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  208.56 + * to extend the choice of license to its licensees as provided above.
  208.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  208.58 + * Version 2 license, then the option applies only if the new code is
  208.59 + * made subject to such option by the copyright holder.
  208.60   */
  208.61  package net.java.html.sound;
  208.62  
   209.1 --- a/sound/src/main/java/org/apidesign/html/sound/impl/BrowserAudioEnv.java	Mon Dec 16 17:16:02 2013 +0100
   209.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   209.3 @@ -1,59 +0,0 @@
   209.4 -/**
   209.5 - * HTML via Java(tm) Language Bindings
   209.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   209.7 - *
   209.8 - * This program is free software: you can redistribute it and/or modify
   209.9 - * it under the terms of the GNU General Public License as published by
  209.10 - * the Free Software Foundation, version 2 of the License.
  209.11 - *
  209.12 - * This program is distributed in the hope that it will be useful,
  209.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  209.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  209.15 - * GNU General Public License for more details. apidesign.org
  209.16 - * designates this particular file as subject to the
  209.17 - * "Classpath" exception as provided by apidesign.org
  209.18 - * in the License file that accompanied this code.
  209.19 - *
  209.20 - * You should have received a copy of the GNU General Public License
  209.21 - * along with this program. Look for COPYING file in the top folder.
  209.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  209.23 - */
  209.24 -package org.apidesign.html.sound.impl;
  209.25 -
  209.26 -import net.java.html.js.JavaScriptBody;
  209.27 -import org.apidesign.html.sound.spi.AudioEnvironment;
  209.28 -import org.openide.util.lookup.ServiceProvider;
  209.29 -
  209.30 -/** Registers an audio provider that delegates to HTML5 Audio tag.
  209.31 - *
  209.32 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  209.33 - */
  209.34 -@ServiceProvider(service = AudioEnvironment.class, position = 100)
  209.35 -public final class BrowserAudioEnv implements AudioEnvironment<Object> {
  209.36 -    @Override
  209.37 -    @JavaScriptBody(args = { "src" }, body = ""
  209.38 -        + "if (!Audio) return null;"
  209.39 -        + "return new Audio(src);")
  209.40 -    public Object create(String src) {
  209.41 -        // null if not running in browser
  209.42 -        return null;
  209.43 -    }
  209.44 -
  209.45 -    @Override @JavaScriptBody(args = { "a" }, body = "a.play();")
  209.46 -    public void play(Object a) {
  209.47 -    }
  209.48 -
  209.49 -    @Override @JavaScriptBody(args = { "a" }, body = "a.pause();")
  209.50 -    public void pause(Object a) {
  209.51 -    }
  209.52 -
  209.53 -    @Override @JavaScriptBody(args = { "a", "volume" }, body = "a.setVolume(volume);")
  209.54 -    public void setVolume(Object a, double volume) {
  209.55 -    }
  209.56 -
  209.57 -    @Override
  209.58 -    @JavaScriptBody(args = "a", body = "return true;")
  209.59 -    public boolean isSupported(Object a) {
  209.60 -        return false;
  209.61 -    }
  209.62 -}
   210.1 --- a/sound/src/main/java/org/apidesign/html/sound/spi/AudioEnvironment.java	Mon Dec 16 17:16:02 2013 +0100
   210.2 +++ b/sound/src/main/java/org/apidesign/html/sound/spi/AudioEnvironment.java	Mon Dec 16 17:16:40 2013 +0100
   210.3 @@ -1,22 +1,44 @@
   210.4  /**
   210.5 - * HTML via Java(tm) Language Bindings
   210.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   210.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   210.8   *
   210.9 - * This program is free software: you can redistribute it and/or modify
  210.10 - * it under the terms of the GNU General Public License as published by
  210.11 - * the Free Software Foundation, version 2 of the License.
  210.12 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  210.13   *
  210.14 - * This program is distributed in the hope that it will be useful,
  210.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  210.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  210.17 - * GNU General Public License for more details. apidesign.org
  210.18 - * designates this particular file as subject to the
  210.19 - * "Classpath" exception as provided by apidesign.org
  210.20 - * in the License file that accompanied this code.
  210.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  210.22 + * Other names may be trademarks of their respective owners.
  210.23   *
  210.24 - * You should have received a copy of the GNU General Public License
  210.25 - * along with this program. Look for COPYING file in the top folder.
  210.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
  210.27 + * The contents of this file are subject to the terms of either the GNU
  210.28 + * General Public License Version 2 only ("GPL") or the Common
  210.29 + * Development and Distribution License("CDDL") (collectively, the
  210.30 + * "License"). You may not use this file except in compliance with the
  210.31 + * License. You can obtain a copy of the License at
  210.32 + * http://www.netbeans.org/cddl-gplv2.html
  210.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  210.34 + * specific language governing permissions and limitations under the
  210.35 + * License.  When distributing the software, include this License Header
  210.36 + * Notice in each file and include the License file at
  210.37 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  210.38 + * particular file as subject to the "Classpath" exception as provided
  210.39 + * by Oracle in the GPL Version 2 section of the License file that
  210.40 + * accompanied this code. If applicable, add the following below the
  210.41 + * License Header, with the fields enclosed by brackets [] replaced by
  210.42 + * your own identifying information:
  210.43 + * "Portions Copyrighted [year] [name of copyright owner]"
  210.44 + *
  210.45 + * Contributor(s):
  210.46 + *
  210.47 + * The Original Software is NetBeans. The Initial Developer of the Original
  210.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  210.49 + *
  210.50 + * If you wish your version of this file to be governed by only the CDDL
  210.51 + * or only the GPL Version 2, indicate your decision by adding
  210.52 + * "[Contributor] elects to include this software in this distribution
  210.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  210.54 + * single choice of license, a recipient has the option to distribute
  210.55 + * your version of this file under either the CDDL, the GPL Version 2 or
  210.56 + * to extend the choice of license to its licensees as provided above.
  210.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  210.58 + * Version 2 license, then the option applies only if the new code is
  210.59 + * made subject to such option by the copyright holder.
  210.60   */
  210.61  package org.apidesign.html.sound.spi;
  210.62  
   211.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   211.2 +++ b/sound/src/main/java/org/netbeans/html/sound/impl/BrowserAudioEnv.java	Mon Dec 16 17:16:40 2013 +0100
   211.3 @@ -0,0 +1,81 @@
   211.4 +/**
   211.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   211.6 + *
   211.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   211.8 + *
   211.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  211.10 + * Other names may be trademarks of their respective owners.
  211.11 + *
  211.12 + * The contents of this file are subject to the terms of either the GNU
  211.13 + * General Public License Version 2 only ("GPL") or the Common
  211.14 + * Development and Distribution License("CDDL") (collectively, the
  211.15 + * "License"). You may not use this file except in compliance with the
  211.16 + * License. You can obtain a copy of the License at
  211.17 + * http://www.netbeans.org/cddl-gplv2.html
  211.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  211.19 + * specific language governing permissions and limitations under the
  211.20 + * License.  When distributing the software, include this License Header
  211.21 + * Notice in each file and include the License file at
  211.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  211.23 + * particular file as subject to the "Classpath" exception as provided
  211.24 + * by Oracle in the GPL Version 2 section of the License file that
  211.25 + * accompanied this code. If applicable, add the following below the
  211.26 + * License Header, with the fields enclosed by brackets [] replaced by
  211.27 + * your own identifying information:
  211.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  211.29 + *
  211.30 + * Contributor(s):
  211.31 + *
  211.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  211.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
  211.34 + *
  211.35 + * If you wish your version of this file to be governed by only the CDDL
  211.36 + * or only the GPL Version 2, indicate your decision by adding
  211.37 + * "[Contributor] elects to include this software in this distribution
  211.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  211.39 + * single choice of license, a recipient has the option to distribute
  211.40 + * your version of this file under either the CDDL, the GPL Version 2 or
  211.41 + * to extend the choice of license to its licensees as provided above.
  211.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  211.43 + * Version 2 license, then the option applies only if the new code is
  211.44 + * made subject to such option by the copyright holder.
  211.45 + */
  211.46 +package org.netbeans.html.sound.impl;
  211.47 +
  211.48 +import net.java.html.js.JavaScriptBody;
  211.49 +import org.apidesign.html.sound.spi.AudioEnvironment;
  211.50 +import org.openide.util.lookup.ServiceProvider;
  211.51 +
  211.52 +/** Registers an audio provider that delegates to HTML5 Audio tag.
  211.53 + *
  211.54 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  211.55 + */
  211.56 +@ServiceProvider(service = AudioEnvironment.class, position = 100)
  211.57 +public final class BrowserAudioEnv implements AudioEnvironment<Object> {
  211.58 +    @Override
  211.59 +    @JavaScriptBody(args = { "src" }, body = ""
  211.60 +        + "if (!Audio) return null;"
  211.61 +        + "return new Audio(src);")
  211.62 +    public Object create(String src) {
  211.63 +        // null if not running in browser
  211.64 +        return null;
  211.65 +    }
  211.66 +
  211.67 +    @Override @JavaScriptBody(args = { "a" }, body = "a.play();")
  211.68 +    public void play(Object a) {
  211.69 +    }
  211.70 +
  211.71 +    @Override @JavaScriptBody(args = { "a" }, body = "a.pause();")
  211.72 +    public void pause(Object a) {
  211.73 +    }
  211.74 +
  211.75 +    @Override @JavaScriptBody(args = { "a", "volume" }, body = "a.setVolume(volume);")
  211.76 +    public void setVolume(Object a, double volume) {
  211.77 +    }
  211.78 +
  211.79 +    @Override
  211.80 +    @JavaScriptBody(args = "a", body = "return true;")
  211.81 +    public boolean isSupported(Object a) {
  211.82 +        return false;
  211.83 +    }
  211.84 +}