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 * <dependency>
26.81 - * <groupId>org.apidesign.html</groupId>
26.82 - * <artifactId>boot-fx</artifactId>
26.83 + * <groupId>org.netbeans.html</groupId>
26.84 + * <artifactId>net.java.html.boot.fx</artifactId>
26.85 * <scope>runtime</scope>
26.86 * </dependency>
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("¶m" + 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("¶m" + 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("¶m" + 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("¶m" + 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 +}